diff --git a/src/facade/conn_context.h b/src/facade/conn_context.h index c32840474..825b45c81 100644 --- a/src/facade/conn_context.h +++ b/src/facade/conn_context.h @@ -36,11 +36,6 @@ class ConnectionContext { return protocol_; } - // A convenient proxy for redis interface. - // Use with caution -- should only be used only - // in execution paths that are Redis *only* - RedisReplyBuilder* operator->(); - SinkReplyBuilder* reply_builder() { return rbuilder_.get(); } @@ -56,8 +51,28 @@ class ConnectionContext { rbuilder_->SendError(str, type); } - void SendError(ErrorReply&& error) { - rbuilder_->SendError(std::move(error)); + void SendError(ErrorReply error) { + rbuilder_->SendError(error); + } + + void SendError(OpStatus status) { + rbuilder_->SendError(status); + } + + void SendStored() { + rbuilder_->SendStored(); + } + + void SendSetSkipped() { + rbuilder_->SendSetSkipped(); + } + + void SendMGetResponse(SinkReplyBuilder::MGetResponse resp) { + rbuilder_->SendMGetResponse(std::move(resp)); + } + + void SendLong(long val) { + rbuilder_->SendLong(val); } void SendSimpleString(std::string_view str) { @@ -68,6 +83,10 @@ class ConnectionContext { rbuilder_->SendOk(); } + void SendProtocolError(std::string_view str) { + rbuilder_->SendProtocolError(str); + } + virtual size_t UsedMemory() const { return dfly::HeapSize(rbuilder_); } diff --git a/src/facade/facade.cc b/src/facade/facade.cc index 91fa3f9a8..b4c98e547 100644 --- a/src/facade/facade.cc +++ b/src/facade/facade.cc @@ -138,12 +138,6 @@ ConnectionContext::ConnectionContext(::io::Sink* stream, Connection* owner) : ow subscriptions = 0; } -RedisReplyBuilder* ConnectionContext::operator->() { - CHECK(Protocol::REDIS == protocol()); - - return static_cast(rbuilder_.get()); -} - CommandId::CommandId(const char* name, uint32_t mask, int8_t arity, int8_t first_key, int8_t last_key, uint32_t acl_categories) : name_(name), diff --git a/src/facade/ok_main.cc b/src/facade/ok_main.cc index 925977ebf..b4559f7a4 100644 --- a/src/facade/ok_main.cc +++ b/src/facade/ok_main.cc @@ -24,7 +24,7 @@ thread_local ConnectionStats tl_stats; class OkService : public ServiceInterface { public: void DispatchCommand(CmdArgList args, ConnectionContext* cntx) final { - (*cntx)->SendOk(); + cntx->SendOk(); } size_t DispatchManyCommands(absl::Span args_lists, ConnectionContext* cntx) final { diff --git a/src/server/acl/acl_family.cc b/src/server/acl/acl_family.cc index dcb1f7715..9e3c94064 100644 --- a/src/server/acl/acl_family.cc +++ b/src/server/acl/acl_family.cc @@ -50,13 +50,14 @@ AclFamily::AclFamily(UserRegistry* registry, util::ProactorPool* pool) } void AclFamily::Acl(CmdArgList args, ConnectionContext* cntx) { - (*cntx)->SendError("Wrong number of arguments for acl command"); + cntx->SendError("Wrong number of arguments for acl command"); } void AclFamily::List(CmdArgList args, ConnectionContext* cntx) { const auto registry_with_lock = registry_->GetRegistryWithLock(); const auto& registry = registry_with_lock.registry; - (*cntx)->StartArray(registry.size()); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(registry.size()); for (const auto& [username, user] : registry) { std::string buffer = "user "; @@ -71,7 +72,7 @@ void AclFamily::List(CmdArgList args, ConnectionContext* cntx) { absl::StrAppend(&buffer, username, " ", user.IsActive() ? "on "sv : "off "sv, password, " ", acl_cat, maybe_space, acl_commands); - (*cntx)->SendSimpleString(buffer); + cntx->SendSimpleString(buffer); } } @@ -97,7 +98,7 @@ using facade::ErrorReply; void AclFamily::SetUser(CmdArgList args, ConnectionContext* cntx) { std::string_view username = facade::ToSV(args[0]); auto req = ParseAclSetUser(args.subspan(1), *cmd_registry_); - auto error_case = [cntx](ErrorReply&& error) { (*cntx)->SendError(error); }; + auto error_case = [cntx](ErrorReply&& error) { cntx->SendError(std::move(error)); }; auto update_case = [username, cntx, this](User::UpdateRequest&& req) { auto user_with_lock = registry_->MaybeAddAndUpdateWithLock(username, std::move(req)); if (user_with_lock.exists) { @@ -313,7 +314,7 @@ void AclFamily::Load(CmdArgList args, ConnectionContext* cntx) { void AclFamily::Log(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 1) { - (*cntx)->SendError(facade::OpStatus::OUT_OF_RANGE); + cntx->SendError(facade::OpStatus::OUT_OF_RANGE); } size_t max_output = 10; @@ -322,12 +323,12 @@ void AclFamily::Log(CmdArgList args, ConnectionContext* cntx) { if (absl::EqualsIgnoreCase(option, "RESET")) { pool_->AwaitFiberOnAll( [](auto index, auto* context) { ServerState::tlocal()->acl_log.Reset(); }); - (*cntx)->SendOk(); + cntx->SendOk(); return; } if (!absl::SimpleAtoi(facade::ToSV(args[0]), &max_output)) { - (*cntx)->SendError("Invalid count"); + cntx->SendError("Invalid count"); return; } } @@ -342,32 +343,33 @@ void AclFamily::Log(CmdArgList args, ConnectionContext* cntx) { total_entries += log.size(); } + auto* rb = static_cast(cntx->reply_builder()); if (total_entries == 0) { - (*cntx)->SendEmptyArray(); + rb->SendEmptyArray(); return; } - (*cntx)->StartArray(total_entries); - auto print_element = [cntx](const auto& entry) { - (*cntx)->StartArray(12); - (*cntx)->SendSimpleString("reason"); + rb->StartArray(total_entries); + auto print_element = [rb](const auto& entry) { + rb->StartArray(12); + rb->SendSimpleString("reason"); using Reason = AclLog::Reason; std::string_view reason = entry.reason == Reason::COMMAND ? "COMMAND" : "AUTH"; - (*cntx)->SendSimpleString(reason); - (*cntx)->SendSimpleString("object"); - (*cntx)->SendSimpleString(entry.object); - (*cntx)->SendSimpleString("username"); - (*cntx)->SendSimpleString(entry.username); - (*cntx)->SendSimpleString("age-seconds"); + rb->SendSimpleString(reason); + rb->SendSimpleString("object"); + rb->SendSimpleString(entry.object); + rb->SendSimpleString("username"); + rb->SendSimpleString(entry.username); + rb->SendSimpleString("age-seconds"); auto now_diff = std::chrono::system_clock::now() - entry.entry_creation; auto secs = std::chrono::duration_cast(now_diff); auto left_over = now_diff - std::chrono::duration_cast(secs); auto age = absl::StrCat(secs.count(), ".", left_over.count()); - (*cntx)->SendSimpleString(absl::StrCat(age)); - (*cntx)->SendSimpleString("client-info"); - (*cntx)->SendSimpleString(entry.client_info); - (*cntx)->SendSimpleString("timestamp-created"); - (*cntx)->SendLong(entry.entry_creation.time_since_epoch().count()); + rb->SendSimpleString(absl::StrCat(age)); + rb->SendSimpleString("client-info"); + rb->SendSimpleString(entry.client_info); + rb->SendSimpleString("timestamp-created"); + rb->SendLong(entry.entry_creation.time_since_epoch().count()); }; auto n_way_minimum = [](const auto& logs) { @@ -394,15 +396,16 @@ void AclFamily::Log(CmdArgList args, ConnectionContext* cntx) { void AclFamily::Users(CmdArgList args, ConnectionContext* cntx) { const auto registry_with_lock = registry_->GetRegistryWithLock(); const auto& registry = registry_with_lock.registry; - (*cntx)->StartArray(registry.size()); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(registry.size()); for (const auto& [username, _] : registry) { - (*cntx)->SendSimpleString(username); + rb->SendSimpleString(username); } } void AclFamily::Cat(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 1) { - (*cntx)->SendError(facade::OpStatus::SYNTAX_ERR); + cntx->SendError(facade::OpStatus::SYNTAX_ERR); return; } @@ -411,7 +414,7 @@ void AclFamily::Cat(CmdArgList args, ConnectionContext* cntx) { std::string_view category = facade::ToSV(args[0]); if (!CATEGORY_INDEX_TABLE.contains(category)) { auto error = absl::StrCat("Unkown category: ", category); - (*cntx)->SendError(error); + cntx->SendError(error); return; } @@ -423,10 +426,11 @@ void AclFamily::Cat(CmdArgList args, ConnectionContext* cntx) { } }; + auto* rb = static_cast(cntx->reply_builder()); cmd_registry_->Traverse(cb); - (*cntx)->StartArray(results.size()); + rb->StartArray(results.size()); for (const auto& command : results) { - (*cntx)->SendSimpleString(command); + rb->SendSimpleString(command); } return; @@ -439,10 +443,11 @@ void AclFamily::Cat(CmdArgList args, ConnectionContext* cntx) { } } - (*cntx)->StartArray(total_categories); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(total_categories); for (auto& elem : REVERSE_CATEGORY_INDEX_TABLE) { if (elem != "_RESERVED") { - (*cntx)->SendSimpleString(elem); + rb->SendSimpleString(elem); } } } @@ -453,39 +458,40 @@ void AclFamily::GetUser(CmdArgList args, ConnectionContext* cntx) { const auto& registry = registry_with_lock.registry; if (!registry.contains(username)) { auto error = absl::StrCat("User: ", username, " does not exists!"); - (*cntx)->SendError(error); + cntx->SendError(error); return; } auto& user = registry.find(username)->second; std::string status = user.IsActive() ? "on" : "off"; auto pass = user.Password(); - (*cntx)->StartArray(6); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(6); - (*cntx)->SendSimpleString("flags"); + rb->SendSimpleString("flags"); const size_t total_elements = (pass != "nopass") ? 1 : 2; - (*cntx)->StartArray(total_elements); - (*cntx)->SendSimpleString(status); + rb->StartArray(total_elements); + rb->SendSimpleString(status); if (total_elements == 2) { - (*cntx)->SendSimpleString(pass); + rb->SendSimpleString(pass); } - (*cntx)->SendSimpleString("passwords"); + rb->SendSimpleString("passwords"); if (pass != "nopass") { - (*cntx)->SendSimpleString(pass); + rb->SendSimpleString(pass); } else { - (*cntx)->SendEmptyArray(); + rb->SendEmptyArray(); } - (*cntx)->SendSimpleString("commands"); + rb->SendSimpleString("commands"); std::string acl = absl::StrCat(AclCatToString(user.AclCategory()), " ", AclCommandToString(user.AclCommandsRef())); - (*cntx)->SendSimpleString(acl); + rb->SendSimpleString(acl); } void AclFamily::GenPass(CmdArgList args, ConnectionContext* cntx) { if (args.length() > 1) { - (*cntx)->SendError(facade::UnknownSubCmd("GENPASS", "ACL")); + cntx->SendError(facade::UnknownSubCmd("GENPASS", "ACL")); return; } uint32_t random_bits = 256; @@ -493,7 +499,7 @@ void AclFamily::GenPass(CmdArgList args, ConnectionContext* cntx) { auto requested_bits = facade::ArgS(args, 0); if (!absl::SimpleAtoi(requested_bits, &random_bits) || random_bits == 0 || random_bits > 4096) { - return (*cntx)->SendError( + return cntx->SendError( "ACL GENPASS argument must be the number of bits for the output password, a positive " "number up to 4096"); } @@ -508,7 +514,7 @@ void AclFamily::GenPass(CmdArgList args, ConnectionContext* cntx) { response.resize(result_length); - (*cntx)->SendSimpleString(response); + cntx->SendSimpleString(response); } void AclFamily::DryRun(CmdArgList args, ConnectionContext* cntx) { @@ -517,7 +523,7 @@ void AclFamily::DryRun(CmdArgList args, ConnectionContext* cntx) { const auto& registry = registry_with_lock.registry; if (!registry.contains(username)) { auto error = absl::StrCat("User: ", username, " does not exists!"); - (*cntx)->SendError(error); + cntx->SendError(error); return; } @@ -526,18 +532,18 @@ void AclFamily::DryRun(CmdArgList args, ConnectionContext* cntx) { auto* cid = cmd_registry_->Find(command); if (!cid) { auto error = absl::StrCat("Command: ", command, " does not exists!"); - (*cntx)->SendError(error); + cntx->SendError(error); return; } const auto& user = registry.find(username)->second; if (IsUserAllowedToInvokeCommandGeneric(user.AclCategory(), user.AclCommandsRef(), *cid)) { - (*cntx)->SendOk(); + cntx->SendOk(); return; } auto error = absl::StrCat("User: ", username, " is not allowed to execute command: ", command); - (*cntx)->SendError(error); + cntx->SendError(error); } using MemberFunc = void (AclFamily::*)(CmdArgList args, ConnectionContext* cntx); diff --git a/src/server/bitops_family.cc b/src/server/bitops_family.cc index 4c91f7baa..d9159b7d7 100644 --- a/src/server/bitops_family.cc +++ b/src/server/bitops_family.cc @@ -500,17 +500,17 @@ template void HandleOpValueResult(const OpResult& result, Connec "we are only handling types that are integral types in the return types from " "here"); if (result) { - (*cntx)->SendLong(result.value()); + cntx->SendLong(result.value()); } else { switch (result.status()) { case OpStatus::WRONG_TYPE: - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); break; case OpStatus::OUT_OF_MEMORY: - (*cntx)->SendError(kOutOfMemory); + cntx->SendError(kOutOfMemory); break; default: - (*cntx)->SendLong(0); // in case we don't have the value we should just send 0 + cntx->SendLong(0); // in case we don't have the value we should just send 0 break; } } @@ -523,7 +523,7 @@ void BitPos(CmdArgList args, ConnectionContext* cntx) { // See details at https://redis.io/commands/bitpos/ if (args.size() < 1 || args.size() > 5) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } std::string_view key = ArgS(args, 0); @@ -534,21 +534,21 @@ void BitPos(CmdArgList args, ConnectionContext* cntx) { bool as_bit = false; if (!absl::SimpleAtoi(ArgS(args, 1), &value)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (args.size() >= 3) { if (!absl::SimpleAtoi(ArgS(args, 2), &start)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (args.size() >= 4) { if (!absl::SimpleAtoi(ArgS(args, 3), &end)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (args.size() >= 5) { if (!ToUpperAndGetAsBit(args, 4, &as_bit)) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } } @@ -568,7 +568,7 @@ void BitCount(CmdArgList args, ConnectionContext* cntx) { // Please note that if the key don't exists, it would return 0 if (args.size() == 2 || args.size() > 4) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } std::string_view key = ArgS(args, 0); @@ -578,11 +578,11 @@ void BitCount(CmdArgList args, ConnectionContext* cntx) { if (args.size() >= 3) { if (absl::SimpleAtoi(ArgS(args, 1), &start) == 0 || absl::SimpleAtoi(ArgS(args, 2), &end) == 0) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (args.size() == 4) { if (!ToUpperAndGetAsBit(args, 3, &as_bit)) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } } @@ -1068,26 +1068,28 @@ nonstd::expected ParseToCommandList(CmdArgList args, b } void SendResults(const std::vector& results, ConnectionContext* cntx) { + auto* rb = static_cast(cntx->reply_builder()); const size_t total = results.size(); if (total == 0) { - (*cntx)->SendNullArray(); + rb->SendNullArray(); return; } - (*cntx)->StartArray(total); + rb->StartArray(total); for (const auto& elem : results) { if (elem) { - (*cntx)->SendLong(*elem); + rb->SendLong(*elem); continue; } - (*cntx)->SendNull(); + rb->SendNull(); } } void BitFieldGeneric(CmdArgList args, bool read_only, ConnectionContext* cntx) { if (args.size() == 1) { - (*cntx)->SendNullArray(); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendNullArray(); return; } auto key = ArgS(args, 0); @@ -1136,7 +1138,7 @@ void BitOp(CmdArgList args, ConnectionContext* cntx) { [&op](auto val) { return op == val; }); if (illegal || (op == NOT_OP_NAME && args.size() > 3)) { - return (*cntx)->SendError(kSyntaxErr); // too many arguments + return cntx->SendError(kSyntaxErr); // too many arguments } // Multi shard access - read only @@ -1166,7 +1168,7 @@ void BitOp(CmdArgList args, ConnectionContext* cntx) { // Second phase - save to targe key if successful if (!joined_results) { cntx->transaction->Conclude(); - (*cntx)->SendError(joined_results.status()); + cntx->SendError(joined_results.status()); return; } else { auto op_result = joined_results.value(); @@ -1187,7 +1189,7 @@ void BitOp(CmdArgList args, ConnectionContext* cntx) { }; cntx->transaction->Execute(std::move(store_cb), true); - (*cntx)->SendLong(op_result.size()); + cntx->SendLong(op_result.size()); } } @@ -1199,7 +1201,7 @@ void GetBit(CmdArgList args, ConnectionContext* cntx) { std::string_view key = ArgS(args, 0); if (!absl::SimpleAtoi(ArgS(args, 1), &offset)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } auto cb = [&](Transaction* t, EngineShard* shard) { return ReadValueBitsetAt(t->GetOpArgs(shard), key, offset); @@ -1218,7 +1220,7 @@ void SetBit(CmdArgList args, ConnectionContext* cntx) { std::string_view key = ArgS(args, 0); if (!absl::SimpleAtoi(ArgS(args, 1), &offset) || !absl::SimpleAtoi(ArgS(args, 2), &value)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } auto cb = [&](Transaction* t, EngineShard* shard) { diff --git a/src/server/cluster/cluster_family.cc b/src/server/cluster/cluster_family.cc index 6e0a81652..5ebb119ef 100644 --- a/src/server/cluster/cluster_family.cc +++ b/src/server/cluster/cluster_family.cc @@ -107,46 +107,48 @@ void ClusterFamily::ClusterHelp(ConnectionContext* cntx) { "HELP", " Prints this help.", }; - return (*cntx)->SendSimpleStrArr(help_arr); + auto* rb = static_cast(cntx->reply_builder()); + return rb->SendSimpleStrArr(help_arr); } namespace { void ClusterShardsImpl(const ClusterShards& config, ConnectionContext* cntx) { // For more details https://redis.io/commands/cluster-shards/ constexpr unsigned int kEntrySize = 4; + auto* rb = static_cast(cntx->reply_builder()); auto WriteNode = [&](const Node& node, string_view role) { constexpr unsigned int kNodeSize = 14; - (*cntx)->StartArray(kNodeSize); - (*cntx)->SendBulkString("id"); - (*cntx)->SendBulkString(node.id); - (*cntx)->SendBulkString("endpoint"); - (*cntx)->SendBulkString(node.ip); - (*cntx)->SendBulkString("ip"); - (*cntx)->SendBulkString(node.ip); - (*cntx)->SendBulkString("port"); - (*cntx)->SendLong(node.port); - (*cntx)->SendBulkString("role"); - (*cntx)->SendBulkString(role); - (*cntx)->SendBulkString("replication-offset"); - (*cntx)->SendLong(0); - (*cntx)->SendBulkString("health"); - (*cntx)->SendBulkString("online"); + rb->StartArray(kNodeSize); + rb->SendBulkString("id"); + rb->SendBulkString(node.id); + rb->SendBulkString("endpoint"); + rb->SendBulkString(node.ip); + rb->SendBulkString("ip"); + rb->SendBulkString(node.ip); + rb->SendBulkString("port"); + rb->SendLong(node.port); + rb->SendBulkString("role"); + rb->SendBulkString(role); + rb->SendBulkString("replication-offset"); + rb->SendLong(0); + rb->SendBulkString("health"); + rb->SendBulkString("online"); }; - (*cntx)->StartArray(config.size()); + rb->StartArray(config.size()); for (const auto& shard : config) { - (*cntx)->StartArray(kEntrySize); - (*cntx)->SendBulkString("slots"); + rb->StartArray(kEntrySize); + rb->SendBulkString("slots"); - (*cntx)->StartArray(shard.slot_ranges.size() * 2); + rb->StartArray(shard.slot_ranges.size() * 2); for (const auto& slot_range : shard.slot_ranges) { - (*cntx)->SendLong(slot_range.start); - (*cntx)->SendLong(slot_range.end); + rb->SendLong(slot_range.start); + rb->SendLong(slot_range.end); } - (*cntx)->SendBulkString("nodes"); - (*cntx)->StartArray(1 + shard.replicas.size()); + rb->SendBulkString("nodes"); + rb->StartArray(1 + shard.replicas.size()); WriteNode(shard.master, "master"); for (const auto& replica : shard.replicas) { WriteNode(replica, "replica"); @@ -161,19 +163,20 @@ void ClusterFamily::ClusterShards(ConnectionContext* cntx) { } else if (tl_cluster_config != nullptr) { return ClusterShardsImpl(tl_cluster_config->GetConfig(), cntx); } else { - return (*cntx)->SendError(kClusterNotConfigured); + return cntx->SendError(kClusterNotConfigured); } } namespace { void ClusterSlotsImpl(const ClusterShards& config, ConnectionContext* cntx) { // For more details https://redis.io/commands/cluster-slots/ + auto* rb = static_cast(cntx->reply_builder()); auto WriteNode = [&](const Node& node) { constexpr unsigned int kNodeSize = 3; - (*cntx)->StartArray(kNodeSize); - (*cntx)->SendBulkString(node.ip); - (*cntx)->SendLong(node.port); - (*cntx)->SendBulkString(node.id); + rb->StartArray(kNodeSize); + rb->SendBulkString(node.ip); + rb->SendLong(node.port); + rb->SendBulkString(node.id); }; unsigned int slot_ranges = 0; @@ -181,14 +184,14 @@ void ClusterSlotsImpl(const ClusterShards& config, ConnectionContext* cntx) { slot_ranges += shard.slot_ranges.size(); } - (*cntx)->StartArray(slot_ranges); + rb->StartArray(slot_ranges); for (const auto& shard : config) { for (const auto& slot_range : shard.slot_ranges) { const unsigned int array_size = /* slot-start, slot-end */ 2 + /* master */ 1 + /* replicas */ shard.replicas.size(); - (*cntx)->StartArray(array_size); - (*cntx)->SendLong(slot_range.start); - (*cntx)->SendLong(slot_range.end); + rb->StartArray(array_size); + rb->SendLong(slot_range.start); + rb->SendLong(slot_range.end); WriteNode(shard.master); for (const auto& replica : shard.replicas) { WriteNode(replica); @@ -204,7 +207,7 @@ void ClusterFamily::ClusterSlots(ConnectionContext* cntx) { } else if (tl_cluster_config != nullptr) { return ClusterSlotsImpl(tl_cluster_config->GetConfig(), cntx); } else { - return (*cntx)->SendError(kClusterNotConfigured); + return cntx->SendError(kClusterNotConfigured); } } @@ -247,7 +250,8 @@ void ClusterNodesImpl(const ClusterShards& config, string_view my_id, Connection } } - return (*cntx)->SendBulkString(result); + auto* rb = static_cast(cntx->reply_builder()); + return rb->SendBulkString(result); } } // namespace @@ -257,7 +261,7 @@ void ClusterFamily::ClusterNodes(ConnectionContext* cntx) { } else if (tl_cluster_config != nullptr) { return ClusterNodesImpl(tl_cluster_config->GetConfig(), server_family_->master_id(), cntx); } else { - return (*cntx)->SendError(kClusterNotConfigured); + return cntx->SendError(kClusterNotConfigured); } } @@ -309,7 +313,8 @@ void ClusterInfoImpl(const ClusterShards& config, ConnectionContext* cntx) { append("cluster_stats_messages_pong_received", 1); append("cluster_stats_messages_meet_received", 0); append("cluster_stats_messages_received", 1); - (*cntx)->SendBulkString(msg); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendBulkString(msg); } } // namespace @@ -325,11 +330,11 @@ void ClusterFamily::ClusterInfo(ConnectionContext* cntx) { void ClusterFamily::KeySlot(CmdArgList args, ConnectionContext* cntx) { if (args.size() != 2) { - return (*cntx)->SendError(WrongNumArgsError("CLUSTER KEYSLOT")); + return cntx->SendError(WrongNumArgsError("CLUSTER KEYSLOT")); } SlotId id = ClusterConfig::KeySlot(ArgS(args, 1)); - return (*cntx)->SendLong(id); + return cntx->SendLong(id); } void ClusterFamily::Cluster(CmdArgList args, ConnectionContext* cntx) { @@ -340,7 +345,7 @@ void ClusterFamily::Cluster(CmdArgList args, ConnectionContext* cntx) { string_view sub_cmd = ArgS(args, 0); if (!ClusterConfig::IsEnabledOrEmulated()) { - return (*cntx)->SendError(kClusterDisabled); + return cntx->SendError(kClusterDisabled); } if (sub_cmd == "HELP") { @@ -356,31 +361,31 @@ void ClusterFamily::Cluster(CmdArgList args, ConnectionContext* cntx) { } else if (sub_cmd == "KEYSLOT") { return KeySlot(args, cntx); } else { - return (*cntx)->SendError(facade::UnknownSubCmd(sub_cmd, "CLUSTER"), facade::kSyntaxErrType); + return cntx->SendError(facade::UnknownSubCmd(sub_cmd, "CLUSTER"), facade::kSyntaxErrType); } } void ClusterFamily::ReadOnly(CmdArgList args, ConnectionContext* cntx) { if (!ClusterConfig::IsEmulated()) { - return (*cntx)->SendError(kClusterDisabled); + return cntx->SendError(kClusterDisabled); } - (*cntx)->SendOk(); + cntx->SendOk(); } void ClusterFamily::ReadWrite(CmdArgList args, ConnectionContext* cntx) { if (!ClusterConfig::IsEmulated()) { - return (*cntx)->SendError(kClusterDisabled); + return cntx->SendError(kClusterDisabled); } - (*cntx)->SendOk(); + cntx->SendOk(); } void ClusterFamily::DflyCluster(CmdArgList args, ConnectionContext* cntx) { if (!ClusterConfig::IsEnabledOrEmulated()) { - return (*cntx)->SendError(kClusterDisabled); + return cntx->SendError(kClusterDisabled); } if (cntx->conn() && !cntx->conn()->IsPrivileged()) { - return (*cntx)->SendError(kDflyClusterCmdPort); + return cntx->SendError(kDflyClusterCmdPort); } ToUpper(&args[0]); @@ -400,14 +405,15 @@ void ClusterFamily::DflyCluster(CmdArgList args, ConnectionContext* cntx) { return DflySlotMigrationStatus(args, cntx); } - return (*cntx)->SendError(UnknownSubCmd(sub_cmd, "DFLYCLUSTER"), kSyntaxErrType); + return cntx->SendError(UnknownSubCmd(sub_cmd, "DFLYCLUSTER"), kSyntaxErrType); } void ClusterFamily::DflyClusterMyId(CmdArgList args, ConnectionContext* cntx) { if (!args.empty()) { - return (*cntx)->SendError(WrongNumArgsError("DFLYCLUSTER MYID")); + return cntx->SendError(WrongNumArgsError("DFLYCLUSTER MYID")); } - (*cntx)->SendBulkString(server_family_->master_id()); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendBulkString(server_family_->master_id()); } namespace { @@ -533,17 +539,18 @@ void ClusterFamily::DflyClusterConfig(CmdArgList args, ConnectionContext* cntx) void ClusterFamily::DflyClusterGetSlotInfo(CmdArgList args, ConnectionContext* cntx) { CmdArgParser parser(args); parser.ExpectTag("SLOTS"); + auto* rb = static_cast(cntx->reply_builder()); vector> slots_stats; do { auto sid = parser.Next(); if (sid > ClusterConfig::kMaxSlotNum) - return (*cntx)->SendError("Invalid slot id"); + return rb->SendError("Invalid slot id"); slots_stats.emplace_back(sid, SlotStats{}); } while (parser.HasNext()); if (auto err = parser.Error(); err) - return (*cntx)->SendError(err->MakeReply()); + return rb->SendError(err->MakeReply()); Mutex mu; @@ -560,36 +567,34 @@ void ClusterFamily::DflyClusterGetSlotInfo(CmdArgList args, ConnectionContext* c shard_set->pool()->AwaitFiberOnAll(std::move(cb)); - (*cntx)->StartArray(slots_stats.size()); + rb->StartArray(slots_stats.size()); for (const auto& slot_data : slots_stats) { - (*cntx)->StartArray(7); - (*cntx)->SendLong(slot_data.first); - (*cntx)->SendBulkString("key_count"); - (*cntx)->SendLong(static_cast(slot_data.second.key_count)); - (*cntx)->SendBulkString("total_reads"); - (*cntx)->SendLong(static_cast(slot_data.second.total_reads)); - (*cntx)->SendBulkString("total_writes"); - (*cntx)->SendLong(static_cast(slot_data.second.total_writes)); + rb->StartArray(7); + rb->SendLong(slot_data.first); + rb->SendBulkString("key_count"); + rb->SendLong(static_cast(slot_data.second.key_count)); + rb->SendBulkString("total_reads"); + rb->SendLong(static_cast(slot_data.second.total_reads)); + rb->SendBulkString("total_writes"); + rb->SendLong(static_cast(slot_data.second.total_writes)); } } void ClusterFamily::DflyClusterFlushSlots(CmdArgList args, ConnectionContext* cntx) { - SinkReplyBuilder* rb = cntx->reply_builder(); - SlotSet slots; slots.reserve(args.size()); for (size_t i = 0; i < args.size(); ++i) { unsigned slot; if (!absl::SimpleAtoi(ArgS(args, i), &slot) || (slot > ClusterConfig::kMaxSlotNum)) { - return rb->SendError(kSyntaxErrType); + return cntx->SendError(kSyntaxErrType); } slots.insert(static_cast(slot)); } DeleteSlots(slots); - return rb->SendOk(); + return cntx->SendOk(); } void ClusterFamily::DflyClusterStartSlotMigration(CmdArgList args, ConnectionContext* cntx) { @@ -601,26 +606,24 @@ void ClusterFamily::DflyClusterStartSlotMigration(CmdArgList args, ConnectionCon slots.emplace_back(SlotRange{slot_start, slot_end}); } while (parser.HasNext()); - SinkReplyBuilder* rb = cntx->reply_builder(); if (auto err = parser.Error(); err) - return rb->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); auto* node = AddMigration(std::string(host_ip), port, std::move(slots)); if (!node) { - return rb->SendError("Can't start the migration, another one is in progress"); + return cntx->SendError("Can't start the migration, another one is in progress"); } node->Start(cntx); - return rb->SendOk(); + return cntx->SendOk(); } void ClusterFamily::DflySlotMigrationStatus(CmdArgList args, ConnectionContext* cntx) { CmdArgParser parser(args); auto [host_ip, port] = parser.Next(); - SinkReplyBuilder* rb = cntx->reply_builder(); if (auto err = parser.Error(); err) - return rb->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); auto state = [&] { lock_guard lk(migrations_jobs_mu_); @@ -647,7 +650,7 @@ void ClusterFamily::DflySlotMigrationStatus(CmdArgList args, ConnectionContext* return "UNDEFINED_STATE"sv; }(); - return rb->SendSimpleString(state_str); + return cntx->SendSimpleString(state_str); } void ClusterFamily::DflyMigrate(CmdArgList args, ConnectionContext* cntx) { @@ -657,7 +660,7 @@ void ClusterFamily::DflyMigrate(CmdArgList args, ConnectionContext* cntx) { if (sub_cmd == "CONF") { MigrationConf(args, cntx); } else { - (*cntx)->SendError(facade::UnknownSubCmd(sub_cmd, "DFLYMIGRATE"), facade::kSyntaxErrType); + cntx->SendError(facade::UnknownSubCmd(sub_cmd, "DFLYMIGRATE"), facade::kSyntaxErrType); } } @@ -687,10 +690,10 @@ void ClusterFamily::MigrationConf(CmdArgList args, ConnectionContext* cntx) { } while (parser.HasNext()); if (auto err = parser.Error(); err) - return (*cntx)->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); if (!tl_cluster_config) { - (*cntx)->SendError(kClusterNotConfigured); + cntx->SendError(kClusterNotConfigured); return; } @@ -699,7 +702,7 @@ void ClusterFamily::MigrationConf(CmdArgList args, ConnectionContext* cntx) { if (!tl_cluster_config->IsMySlot(i)) { VLOG(1) << "Invalid migration slot " << i << " in range " << migration_range.start << ':' << migration_range.end; - (*cntx)->SendError("Invalid slots range"); + cntx->SendError("Invalid slots range"); return; } } @@ -707,7 +710,7 @@ void ClusterFamily::MigrationConf(CmdArgList args, ConnectionContext* cntx) { cntx->conn()->SetName("slot_migration_ctrl"); - (*cntx)->SendLong(shard_set->size()); + cntx->SendLong(shard_set->size()); return; } diff --git a/src/server/cluster/cluster_slot_migration.cc b/src/server/cluster/cluster_slot_migration.cc index 2b30975e1..4ab6525e6 100644 --- a/src/server/cluster/cluster_slot_migration.cc +++ b/src/server/cluster/cluster_slot_migration.cc @@ -33,7 +33,7 @@ error_code ClusterSlotMigration::Start(ConnectionContext* cntx) { auto check_connection_error = [this, &cntx](error_code ec, const char* msg) -> error_code { if (ec) { - (*cntx)->SendError(absl::StrCat(msg, ec.message())); + cntx->SendError(absl::StrCat(msg, ec.message())); } return ec; }; diff --git a/src/server/conn_context.cc b/src/server/conn_context.cc index d9d91f323..fa97ee50d 100644 --- a/src/server/conn_context.cc +++ b/src/server/conn_context.cc @@ -177,10 +177,11 @@ void ConnectionContext::ChangeSubscription(bool to_add, bool to_reply, CmdArgLis if (to_reply) { for (size_t i = 0; i < result.size(); ++i) { const char* action[2] = {"unsubscribe", "subscribe"}; - (*this)->StartCollection(3, RedisReplyBuilder::CollectionType::PUSH); - (*this)->SendBulkString(action[to_add]); - (*this)->SendBulkString(ArgS(args, i)); - (*this)->SendLong(result[i]); + auto rb = static_cast(reply_builder()); + rb->StartCollection(3, RedisReplyBuilder::CollectionType::PUSH); + rb->SendBulkString(action[to_add]); + rb->SendBulkString(ArgS(args, i)); + rb->SendLong(result[i]); } } } @@ -224,13 +225,14 @@ void ConnectionContext::PUnsubscribeAll(bool to_reply) { void ConnectionContext::SendSubscriptionChangedResponse(string_view action, std::optional topic, unsigned count) { - (*this)->StartCollection(3, RedisReplyBuilder::CollectionType::PUSH); - (*this)->SendBulkString(action); + auto rb = static_cast(reply_builder()); + rb->StartCollection(3, RedisReplyBuilder::CollectionType::PUSH); + rb->SendBulkString(action); if (topic.has_value()) - (*this)->SendBulkString(topic.value()); + rb->SendBulkString(topic.value()); else - (*this)->SendNull(); - (*this)->SendLong(count); + rb->SendNull(); + rb->SendLong(count); } size_t ConnectionContext::UsedMemory() const { diff --git a/src/server/debugcmd.cc b/src/server/debugcmd.cc index 27ceefc25..76482abbb 100644 --- a/src/server/debugcmd.cc +++ b/src/server/debugcmd.cc @@ -251,7 +251,8 @@ void DebugCmd::Run(CmdArgList args) { "HELP", " Prints this help.", }; - return (*cntx_)->SendSimpleStrArr(help_arr); + auto* rb = static_cast(cntx_->reply_builder()); + return rb->SendSimpleStrArr(help_arr); } VLOG(1) << "subcmd " << subcmd; @@ -298,7 +299,7 @@ void DebugCmd::Run(CmdArgList args) { } string reply = UnknownSubCmd(subcmd, "DEBUG"); - return (*cntx_)->SendError(reply, kSyntaxErrType); + return cntx_->SendError(reply, kSyntaxErrType); } void DebugCmd::Reload(CmdArgList args) { @@ -312,7 +313,7 @@ void DebugCmd::Reload(CmdArgList args) { if (opt == "NOSAVE") { save = false; } else { - return (*cntx_)->SendError("DEBUG RELOAD only supports the NOSAVE options."); + return cntx_->SendError("DEBUG RELOAD only supports the NOSAVE options."); } } @@ -322,7 +323,7 @@ void DebugCmd::Reload(CmdArgList args) { GenericError ec = sf_.DoSave(); if (ec) { - return (*cntx_)->SendError(ec.Format()); + return cntx_->SendError(ec.Format()); } } @@ -335,24 +336,25 @@ void DebugCmd::Replica(CmdArgList args) { ToUpper(&args[0]); string_view opt = ArgS(args, 0); + auto* rb = static_cast(cntx_->reply_builder()); if (opt == "PAUSE" || opt == "RESUME") { sf_.PauseReplication(opt == "PAUSE"); - return (*cntx_)->SendOk(); + return rb->SendOk(); } else if (opt == "OFFSET") { const auto offset_info = sf_.GetReplicaOffsetInfo(); if (offset_info) { - (*cntx_)->StartArray(2); - (*cntx_)->SendBulkString(offset_info.value().sync_id); - (*cntx_)->StartArray(offset_info.value().flow_offsets.size()); + rb->StartArray(2); + rb->SendBulkString(offset_info.value().sync_id); + rb->StartArray(offset_info.value().flow_offsets.size()); for (uint64_t offset : offset_info.value().flow_offsets) { - (*cntx_)->SendLong(offset); + rb->SendLong(offset); } return; } else { - return (*cntx_)->SendError("I am master"); + return rb->SendError("I am master"); } } - return (*cntx_)->SendError(UnknownSubCmd("replica", "DEBUG")); + return rb->SendError(UnknownSubCmd("replica", "DEBUG")); } void DebugCmd::Load(string_view filename) { @@ -389,22 +391,22 @@ void DebugCmd::Load(string_view filename) { ec = fut_ec.get(); if (ec) { LOG(INFO) << "Could not load file " << ec.message(); - return (*cntx_)->SendError(ec.message()); + return cntx_->SendError(ec.message()); } } - (*cntx_)->SendOk(); + cntx_->SendOk(); } optional DebugCmd::ParsePopulateArgs(CmdArgList args) { if (args.size() < 2 || args.size() > 8) { - (*cntx_)->SendError(UnknownSubCmd("populate", "DEBUG")); + cntx_->SendError(UnknownSubCmd("populate", "DEBUG")); return nullopt; } PopulateOptions options; if (!absl::SimpleAtoi(ArgS(args, 1), &options.total_count)) { - (*cntx_)->SendError(kUintErr); + cntx_->SendError(kUintErr); return nullopt; } @@ -414,7 +416,7 @@ optional DebugCmd::ParsePopulateArgs(CmdArgList args) if (args.size() > 3) { if (!absl::SimpleAtoi(ArgS(args, 3), &options.val_size)) { - (*cntx_)->SendError(kUintErr); + cntx_->SendError(kUintErr); return nullopt; } } @@ -426,7 +428,7 @@ optional DebugCmd::ParsePopulateArgs(CmdArgList args) options.populate_random_values = true; } else if (str == "SLOTS") { if (args.size() < index + 3) { - (*cntx_)->SendError(kSyntaxErr); + cntx_->SendError(kSyntaxErr); return nullopt; } @@ -443,19 +445,19 @@ optional DebugCmd::ParsePopulateArgs(CmdArgList args) auto start = parse_slot(ArgS(args, ++index)); if (start.status() != facade::OpStatus::OK) { - (*cntx_)->SendError(start.status()); + cntx_->SendError(start.status()); return nullopt; } auto end = parse_slot(ArgS(args, ++index)); if (end.status() != facade::OpStatus::OK) { - (*cntx_)->SendError(end.status()); + cntx_->SendError(end.status()); return nullopt; } options.slot_range = ClusterConfig::SlotRange{.start = static_cast(start.value()), .end = static_cast(end.value())}; } else { - (*cntx_)->SendError(kSyntaxErr); + cntx_->SendError(kSyntaxErr); return nullopt; } } @@ -491,7 +493,7 @@ void DebugCmd::Populate(CmdArgList args) { for (auto& fb : fb_arr) fb.Join(); - (*cntx_)->SendOk(); + cntx_->SendOk(); } void DebugCmd::PopulateRangeFiber(uint64_t from, uint64_t num_of_keys, @@ -607,7 +609,7 @@ void DebugCmd::Inspect(string_view key) { string resp; if (!res.found) { - (*cntx_)->SendError(kKeyNotFoundErr); + cntx_->SendError(kKeyNotFoundErr); return; } @@ -625,7 +627,7 @@ void DebugCmd::Inspect(string_view key) { if (res.lock_status != ObjInfo::NONE) { StrAppend(&resp, " lock:", res.lock_status == ObjInfo::X ? "x" : "s"); } - (*cntx_)->SendSimpleString(resp); + cntx_->SendSimpleString(resp); } void DebugCmd::Watched() { @@ -647,12 +649,13 @@ void DebugCmd::Watched() { } }; + auto* rb = static_cast(cntx_->reply_builder()); shard_set->RunBlockingInParallel(cb); - (*cntx_)->StartArray(4); - (*cntx_)->SendBulkString("awaked"); - (*cntx_)->SendStringArr(awaked_trans); - (*cntx_)->SendBulkString("watched"); - (*cntx_)->SendStringArr(watched_keys); + rb->StartArray(4); + rb->SendBulkString("awaked"); + rb->SendStringArr(awaked_trans); + rb->SendBulkString("watched"); + rb->SendStringArr(watched_keys); } void DebugCmd::TxAnalysis() { @@ -708,8 +711,8 @@ void DebugCmd::TxAnalysis() { shard_set->RunBriefInParallel(cb); - (*cntx_)->SendSimpleString(absl::StrCat("queue_len:", queue_len.load(), - "armed: ", armed_cnt.load(), " free:", free_cnt.load())); + cntx_->SendSimpleString(absl::StrCat("queue_len:", queue_len.load(), "armed: ", armed_cnt.load(), + " free:", free_cnt.load())); } void DebugCmd::ObjHist() { @@ -735,7 +738,8 @@ void DebugCmd::ObjHist() { } absl::StrAppend(&result, "___end object histogram___\n"); - (*cntx_)->SendBulkString(result); + auto* rb = static_cast(cntx_->reply_builder()); + rb->SendBulkString(result); } void DebugCmd::Stacktrace() { @@ -744,7 +748,7 @@ void DebugCmd::Stacktrace() { std::unique_lock lk(m); fb2::detail::FiberInterface::PrintAllFiberStackTraces(); }); - (*cntx_)->SendOk(); + cntx_->SendOk(); } void DebugCmd::Shards() { @@ -798,8 +802,8 @@ void DebugCmd::Shards() { #undef ADD_STAT #undef MAXMIN_STAT - - (*cntx_)->SendBulkString(out); + auto* rb = static_cast(cntx_->reply_builder()); + rb->SendBulkString(out); } } // namespace dfly diff --git a/src/server/dflycmd.cc b/src/server/dflycmd.cc index cacec4772..77eeabb07 100644 --- a/src/server/dflycmd.cc +++ b/src/server/dflycmd.cc @@ -105,8 +105,6 @@ DflyCmd::DflyCmd(ServerFamily* server_family) : sf_(server_family) { } void DflyCmd::Run(CmdArgList args, ConnectionContext* cntx) { - RedisReplyBuilder* rb = static_cast(cntx->reply_builder()); - DCHECK_GE(args.size(), 1u); ToUpper(&args[0]); string_view sub_cmd = ArgS(args, 0); @@ -143,7 +141,7 @@ void DflyCmd::Run(CmdArgList args, ConnectionContext* cntx) { return ReplicaOffset(args, cntx); } - rb->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); } #if 0 @@ -395,7 +393,7 @@ void DflyCmd::TakeOver(CmdArgList args, ConnectionContext* cntx) { parser.Next(); float timeout = parser.Next(); if (timeout < 0) { - return (*cntx)->SendError("timeout is negative"); + return cntx->SendError("timeout is negative"); } bool save_flag = static_cast(parser.Check("SAVE").IgnoreCase()); @@ -403,7 +401,7 @@ void DflyCmd::TakeOver(CmdArgList args, ConnectionContext* cntx) { string_view sync_id_str = parser.Next(); if (auto err = parser.Error(); err) - return (*cntx)->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); VLOG(1) << "Got DFLY TAKEOVER " << sync_id_str << " time out:" << timeout; @@ -479,7 +477,7 @@ void DflyCmd::TakeOver(CmdArgList args, ConnectionContext* cntx) { sf_->service().SwitchState(GlobalState::TAKEN_OVER, GlobalState::ACTIVE); return rb->SendError("Takeover failed!"); } - (*cntx)->SendOk(); + cntx->SendOk(); if (save_flag) { VLOG(1) << "Save snapshot after Takeover."; diff --git a/src/server/generic_family.cc b/src/server/generic_family.cc index a16c411c6..08a0015ac 100644 --- a/src/server/generic_family.cc +++ b/src/server/generic_family.cc @@ -687,24 +687,25 @@ void GenericFamily::Del(CmdArgList args, ConnectionContext* cntx) { mc_builder->SendSimpleString("DELETED"); } } else { - (*cntx)->SendLong(del_cnt); + cntx->SendLong(del_cnt); } } void GenericFamily::Ping(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 1) { - return (*cntx)->SendError(facade::WrongNumArgsError("ping"), kSyntaxErrType); + return cntx->SendError(facade::WrongNumArgsError("ping"), kSyntaxErrType); } // We synchronously block here until the engine sends us the payload and notifies that // the I/O operation has been processed. if (args.size() == 0) { - return (*cntx)->SendSimpleString("PONG"); + return cntx->SendSimpleString("PONG"); } else { string_view arg = ArgS(args, 0); DVLOG(2) << "Ping " << arg; - return (*cntx)->SendBulkString(arg); + auto* rb = static_cast(cntx->reply_builder()); + return rb->SendBulkString(arg); } } @@ -725,7 +726,7 @@ void GenericFamily::Exists(CmdArgList args, ConnectionContext* cntx) { OpStatus status = transaction->ScheduleSingleHop(std::move(cb)); CHECK_EQ(OpStatus::OK, status); - return (*cntx)->SendLong(result.load(memory_order_acquire)); + return cntx->SendLong(result.load(memory_order_acquire)); } void GenericFamily::Persist(CmdArgList args, ConnectionContext* cntx) { @@ -735,9 +736,9 @@ void GenericFamily::Persist(CmdArgList args, ConnectionContext* cntx) { OpStatus status = cntx->transaction->ScheduleSingleHop(move(cb)); if (status == OpStatus::OK) - (*cntx)->SendLong(1); + cntx->SendLong(1); else - (*cntx)->SendLong(0); + cntx->SendLong(0); } std::optional ParseExpireOptionsOrReply(const CmdArgList args, ConnectionContext* cntx) { @@ -754,16 +755,16 @@ std::optional ParseExpireOptionsOrReply(const CmdArgList args, Connecti } else if (arg_sv == "LT") { flags |= ExpireFlags::EXPIRE_LT; } else { - (*cntx)->SendError(absl::StrCat("Unsupported option: ", arg_sv)); + cntx->SendError(absl::StrCat("Unsupported option: ", arg_sv)); return nullopt; } } if ((flags & ExpireFlags::EXPIRE_NX) && (flags & ~ExpireFlags::EXPIRE_NX)) { - (*cntx)->SendError("NX and XX, GT or LT options at the same time are not compatible"); + cntx->SendError("NX and XX, GT or LT options at the same time are not compatible"); return nullopt; } if ((flags & ExpireFlags::EXPIRE_GT) && (flags & ExpireFlags::EXPIRE_LT)) { - (*cntx)->SendError("GT and LT options at the same time are not compatible"); + cntx->SendError("GT and LT options at the same time are not compatible"); return nullopt; } return flags; @@ -775,11 +776,11 @@ void GenericFamily::Expire(CmdArgList args, ConnectionContext* cntx) { int64_t int_arg; if (!absl::SimpleAtoi(sec, &int_arg)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (int_arg > kMaxExpireDeadlineSec || int_arg < -kMaxExpireDeadlineSec) { - return (*cntx)->SendError(InvalidExpireTime(cntx->cid->name())); + return cntx->SendError(InvalidExpireTime(cntx->cid->name())); } int_arg = std::max(int_arg, -1); @@ -794,7 +795,7 @@ void GenericFamily::Expire(CmdArgList args, ConnectionContext* cntx) { }; OpStatus status = cntx->transaction->ScheduleSingleHop(move(cb)); - (*cntx)->SendLong(status == OpStatus::OK); + cntx->SendLong(status == OpStatus::OK); } void GenericFamily::ExpireAt(CmdArgList args, ConnectionContext* cntx) { @@ -803,7 +804,7 @@ void GenericFamily::ExpireAt(CmdArgList args, ConnectionContext* cntx) { int64_t int_arg; if (!absl::SimpleAtoi(sec, &int_arg)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } int_arg = std::max(int_arg, 0L); @@ -820,9 +821,9 @@ void GenericFamily::ExpireAt(CmdArgList args, ConnectionContext* cntx) { OpStatus status = cntx->transaction->ScheduleSingleHop(std::move(cb)); if (status == OpStatus::OUT_OF_RANGE) { - return (*cntx)->SendError(kExpiryOutOfRange); + return cntx->SendError(kExpiryOutOfRange); } else { - (*cntx)->SendLong(status == OpStatus::OK); + cntx->SendLong(status == OpStatus::OK); } } @@ -841,9 +842,10 @@ void GenericFamily::Keys(CmdArgList args, ConnectionContext* cntx) { cursor = ScanGeneric(cursor, scan_opts, &keys, cntx); } while (cursor != 0 && keys.size() < output_limit); - (*cntx)->StartArray(keys.size()); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(keys.size()); for (const auto& k : keys) { - (*cntx)->SendBulkString(k); + rb->SendBulkString(k); } } @@ -853,7 +855,7 @@ void GenericFamily::PexpireAt(CmdArgList args, ConnectionContext* cntx) { int64_t int_arg; if (!absl::SimpleAtoi(msec, &int_arg)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } int_arg = std::max(int_arg, 0L); auto expire_options = ParseExpireOptionsOrReply(args.subspan(2), cntx); @@ -871,9 +873,9 @@ void GenericFamily::PexpireAt(CmdArgList args, ConnectionContext* cntx) { OpStatus status = cntx->transaction->ScheduleSingleHop(std::move(cb)); if (status == OpStatus::OUT_OF_RANGE) { - return (*cntx)->SendError(kExpiryOutOfRange); + return cntx->SendError(kExpiryOutOfRange); } else { - (*cntx)->SendLong(status == OpStatus::OK); + cntx->SendLong(status == OpStatus::OK); } } @@ -883,7 +885,7 @@ void GenericFamily::Pexpire(CmdArgList args, ConnectionContext* cntx) { int64_t int_arg; if (!absl::SimpleAtoi(msec, &int_arg)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } int_arg = std::max(int_arg, 0L); auto expire_options = ParseExpireOptionsOrReply(args.subspan(2), cntx); @@ -899,9 +901,9 @@ void GenericFamily::Pexpire(CmdArgList args, ConnectionContext* cntx) { OpStatus status = cntx->transaction->ScheduleSingleHop(std::move(cb)); if (status == OpStatus::OUT_OF_RANGE) { - return (*cntx)->SendError(kExpiryOutOfRange); + return cntx->SendError(kExpiryOutOfRange); } else { - (*cntx)->SendLong(status == OpStatus::OK); + cntx->SendLong(status == OpStatus::OK); } } @@ -925,7 +927,7 @@ void GenericFamily::Stick(CmdArgList args, ConnectionContext* cntx) { DVLOG(2) << "Stick ts " << transaction->txid(); uint32_t match_cnt = result.load(memory_order_relaxed); - (*cntx)->SendLong(match_cnt); + cntx->SendLong(match_cnt); } // Used to conditionally store double score @@ -1045,11 +1047,11 @@ void GenericFamily::Sort(CmdArgList args, ConnectionContext* cntx) { } else if (arg == "LIMIT") { int offset, limit; if (i + 2 >= args.size()) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } if (!absl::SimpleAtoi(ArgS(args, i + 1), &offset) || !absl::SimpleAtoi(ArgS(args, i + 2), &limit)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } bounds = {offset, limit}; i += 2; @@ -1062,10 +1064,11 @@ void GenericFamily::Sort(CmdArgList args, ConnectionContext* cntx) { }); if (fetch_result.status() == OpStatus::WRONG_TYPE) - return (*cntx)->SendError("One or more scores can't be converted into double"); + return cntx->SendError("One or more scores can't be converted into double"); + auto* rb = static_cast(cntx->reply_builder()); if (!fetch_result.ok()) - return (*cntx)->SendEmptyArray(); + return rb->SendEmptyArray(); auto result_type = fetch_result.type(); auto sort_call = [cntx, bounds, reversed, result_type](auto& entries) { @@ -1089,11 +1092,12 @@ void GenericFamily::Sort(CmdArgList args, ConnectionContext* cntx) { } 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); + auto* rb = static_cast(cntx->reply_builder()); + rb->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); + rb->SendBulkString(it->key); } }; std::visit(std::move(sort_call), fetch_result.value()); @@ -1104,15 +1108,15 @@ void GenericFamily::Restore(CmdArgList args, ConnectionContext* cntx) { std::string_view serialized_value = ArgS(args, 2); int rdb_version = 0; if (!VerifyFooter(serialized_value, &rdb_version)) { - return (*cntx)->SendError("ERR DUMP payload version or checksum are wrong"); + return cntx->SendError("ERR DUMP payload version or checksum are wrong"); } OpResult restore_args = RestoreArgs::TryFrom(args); if (!restore_args) { if (restore_args.status() == OpStatus::OUT_OF_RANGE) { - return (*cntx)->SendError("Invalid IDLETIME value, must be >= 0"); + return cntx->SendError("Invalid IDLETIME value, must be >= 0"); } else { - return (*cntx)->SendError(restore_args.status()); + return cntx->SendError(restore_args.status()); } } @@ -1124,18 +1128,18 @@ void GenericFamily::Restore(CmdArgList args, ConnectionContext* cntx) { if (result) { if (result.value()) { - return (*cntx)->SendOk(); + return cntx->SendOk(); } else { - return (*cntx)->SendError("Bad data format"); + return cntx->SendError("Bad data format"); } } else { switch (result.status()) { case OpStatus::KEY_EXISTS: - return (*cntx)->SendError("BUSYKEY: key name already exists."); + return cntx->SendError("BUSYKEY: key name already exists."); case OpStatus::WRONG_TYPE: - return (*cntx)->SendError("Bad data format"); + return cntx->SendError("Bad data format"); default: - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); } } } @@ -1151,11 +1155,11 @@ void GenericFamily::FieldTtl(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); return; } - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } void GenericFamily::Move(CmdArgList args, ConnectionContext* cntx) { @@ -1164,15 +1168,15 @@ void GenericFamily::Move(CmdArgList args, ConnectionContext* cntx) { int64_t target_db; if (!absl::SimpleAtoi(target_db_sv, &target_db)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (target_db < 0 || target_db >= absl::GetFlag(FLAGS_dbnum)) { - return (*cntx)->SendError(kDbIndOutOfRangeErr); + return cntx->SendError(kDbIndOutOfRangeErr); } if (target_db == cntx->db_index()) { - return (*cntx)->SendError("source and destination objects are the same"); + return cntx->SendError("source and destination objects are the same"); } OpStatus res = OpStatus::SKIPPED; @@ -1194,23 +1198,23 @@ void GenericFamily::Move(CmdArgList args, ConnectionContext* cntx) { cntx->transaction->ScheduleSingleHop(std::move(cb)); // Exactly one shard will call OpMove. DCHECK(res != OpStatus::SKIPPED); - (*cntx)->SendLong(res == OpStatus::OK); + cntx->SendLong(res == OpStatus::OK); } void GenericFamily::Rename(CmdArgList args, ConnectionContext* cntx) { OpResult st = RenameGeneric(args, false, cntx); - (*cntx)->SendError(st.status()); + cntx->SendError(st.status()); } void GenericFamily::RenameNx(CmdArgList args, ConnectionContext* cntx) { OpResult st = RenameGeneric(args, true, cntx); OpStatus status = st.status(); if (status == OpStatus::OK) { - (*cntx)->SendLong(1); + cntx->SendLong(1); } else if (status == OpStatus::KEY_EXISTS) { - (*cntx)->SendLong(0); + cntx->SendLong(0); } else { - (*cntx)->SendError(status); + cntx->SendError(status); } } @@ -1230,18 +1234,18 @@ void GenericFamily::TtlGeneric(CmdArgList args, ConnectionContext* cntx, TimeUni if (result) { long ttl = (unit == TimeUnit::SEC) ? (result.value() + 500) / 1000 : result.value(); - (*cntx)->SendLong(ttl); + cntx->SendLong(ttl); return; } switch (result.status()) { case OpStatus::KEY_NOTFOUND: - (*cntx)->SendLong(-2); + cntx->SendLong(-2); break; default: LOG_IF(ERROR, result.status() != OpStatus::SKIPPED) << "Unexpected status " << result.status(); - (*cntx)->SendLong(-1); + cntx->SendLong(-1); break; } } @@ -1250,13 +1254,13 @@ void GenericFamily::Select(CmdArgList args, ConnectionContext* cntx) { string_view key = ArgS(args, 0); int64_t index; if (!absl::SimpleAtoi(key, &index)) { - return (*cntx)->SendError(kInvalidDbIndErr); + return cntx->SendError(kInvalidDbIndErr); } if (ClusterConfig::IsEnabled() && index != 0) { - return (*cntx)->SendError("SELECT is not allowed in cluster mode"); + return cntx->SendError("SELECT is not allowed in cluster mode"); } if (index < 0 || index >= absl::GetFlag(FLAGS_dbnum)) { - return (*cntx)->SendError(kDbIndOutOfRangeErr); + return cntx->SendError(kDbIndOutOfRangeErr); } cntx->conn_state.db_index = index; auto cb = [index](EngineShard* shard) { @@ -1265,7 +1269,7 @@ void GenericFamily::Select(CmdArgList args, ConnectionContext* cntx) { }; shard_set->RunBriefInParallel(std::move(cb)); - return (*cntx)->SendOk(); + return cntx->SendOk(); } void GenericFamily::Dump(CmdArgList args, ConnectionContext* cntx) { @@ -1275,12 +1279,13 @@ void GenericFamily::Dump(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult result = trans->ScheduleSingleHopT(std::move(cb)); + auto* rb = static_cast(cntx->reply_builder()); if (result) { DVLOG(1) << "Dump " << trans->DebugId() << ": " << key << ", dump size " << result.value().size(); - (*cntx)->SendBulkString(*result); + rb->SendBulkString(*result); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } @@ -1297,9 +1302,9 @@ void GenericFamily::Type(CmdArgList args, ConnectionContext* cntx) { }; OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (!result) { - (*cntx)->SendSimpleString("none"); + cntx->SendSimpleString("none"); } else { - (*cntx)->SendSimpleString(ObjTypeName(result.value())); + cntx->SendSimpleString(ObjTypeName(result.value())); } } @@ -1311,9 +1316,10 @@ void GenericFamily::Time(CmdArgList args, ConnectionContext* cntx) { now_usec = absl::GetCurrentTimeNanos() / 1000; } - (*cntx)->StartArray(2); - (*cntx)->SendLong(now_usec / 1000000); - (*cntx)->SendLong(now_usec % 1000000); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(2); + rb->SendLong(now_usec / 1000000); + rb->SendLong(now_usec % 1000000); } OpResult GenericFamily::RenameGeneric(CmdArgList args, bool skip_exist_dest, @@ -1349,7 +1355,8 @@ OpResult GenericFamily::RenameGeneric(CmdArgList args, bool skip_exist_des void GenericFamily::Echo(CmdArgList args, ConnectionContext* cntx) { string_view key = ArgS(args, 0); - return (*cntx)->SendBulkString(key); + auto* rb = static_cast(cntx->reply_builder()); + return rb->SendBulkString(key); } void GenericFamily::Scan(CmdArgList args, ConnectionContext* cntx) { @@ -1357,13 +1364,13 @@ void GenericFamily::Scan(CmdArgList args, ConnectionContext* cntx) { uint64_t cursor = 0; if (!absl::SimpleAtoi(token, &cursor)) { - return (*cntx)->SendError("invalid cursor"); + return cntx->SendError("invalid cursor"); } OpResult ops = ScanOpts::TryFrom(args.subspan(1)); if (!ops) { DVLOG(1) << "Scan invalid args - return " << ops << " to the user"; - return (*cntx)->SendError(ops.status()); + return cntx->SendError(ops.status()); } ScanOpts scan_op = ops.value(); @@ -1371,11 +1378,12 @@ void GenericFamily::Scan(CmdArgList args, ConnectionContext* cntx) { StringVec keys; cursor = ScanGeneric(cursor, scan_op, &keys, cntx); - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(absl::StrCat(cursor)); - (*cntx)->StartArray(keys.size()); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(2); + rb->SendBulkString(absl::StrCat(cursor)); + rb->StartArray(keys.size()); for (const auto& k : keys) { - (*cntx)->SendBulkString(k); + rb->SendBulkString(k); } } diff --git a/src/server/hll_family.cc b/src/server/hll_family.cc index a238802f3..419bad1e1 100644 --- a/src/server/hll_family.cc +++ b/src/server/hll_family.cc @@ -32,20 +32,20 @@ template void HandleOpValueResult(const OpResult& result, Connec "we are only handling types that are integral types in the return types from " "here"); if (result) { - (*cntx)->SendLong(result.value()); + cntx->SendLong(result.value()); } else { switch (result.status()) { case OpStatus::WRONG_TYPE: - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); break; case OpStatus::OUT_OF_MEMORY: - (*cntx)->SendError(kOutOfMemory); + cntx->SendError(kOutOfMemory); break; case OpStatus::INVALID_VALUE: - (*cntx)->SendError(HllFamily::kInvalidHllErr); + cntx->SendError(HllFamily::kInvalidHllErr); break; default: - (*cntx)->SendLong(0); // in case we don't have the value we should just send 0 + cntx->SendLong(0); // in case we don't have the value we should just send 0 break; } } @@ -275,9 +275,9 @@ void PFMerge(CmdArgList args, ConnectionContext* cntx) { OpResult result = PFMergeInternal(args, cntx); if (result.ok()) { if (result.value() == 0) { - (*cntx)->SendOk(); + cntx->SendOk(); } else { - (*cntx)->SendError(HllFamily::kInvalidHllErr); + cntx->SendError(HllFamily::kInvalidHllErr); } } else { HandleOpValueResult(result, cntx); diff --git a/src/server/hset_family.cc b/src/server/hset_family.cc index 851dce09a..c74508fad 100644 --- a/src/server/hset_family.cc +++ b/src/server/hset_family.cc @@ -709,19 +709,20 @@ void HGetGeneric(CmdArgList args, ConnectionContext* cntx, uint8_t getall_mask) OpResult> result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); + auto* rb = static_cast(cntx->reply_builder()); if (result) { bool is_map = (getall_mask == (VALUES | FIELDS)); - (*cntx)->SendStringArr(absl::Span{*result}, - is_map ? RedisReplyBuilder::MAP : RedisReplyBuilder::ARRAY); + rb->SendStringArr(absl::Span{*result}, + is_map ? RedisReplyBuilder::MAP : RedisReplyBuilder::ARRAY); } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } // HSETEX key tll_sec field value field value ... void HSetEx(CmdArgList args, ConnectionContext* cntx) { if (args.size() % 2 != 0) { - return (*cntx)->SendError(facade::WrongNumArgsError(cntx->cid->name()), kSyntaxErrType); + return cntx->SendError(facade::WrongNumArgsError(cntx->cid->name()), kSyntaxErrType); } string_view key = ArgS(args, 0); @@ -730,7 +731,7 @@ void HSetEx(CmdArgList args, ConnectionContext* cntx) { constexpr uint32_t kMaxTtl = (1UL << 26); if (!absl::SimpleAtoi(ttl_str, &ttl_sec) || ttl_sec == 0 || ttl_sec > kMaxTtl) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } args.remove_prefix(2); @@ -743,9 +744,9 @@ void HSetEx(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -761,9 +762,9 @@ void HSetFamily::HDel(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result || result.status() == OpStatus::KEY_NOTFOUND) { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -774,9 +775,9 @@ void HSetFamily::HLen(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -790,9 +791,9 @@ void HSetFamily::HExists(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -806,26 +807,27 @@ void HSetFamily::HMGet(CmdArgList args, ConnectionContext* cntx) { OpResult> result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); + auto* rb = static_cast(cntx->reply_builder()); if (result) { SinkReplyBuilder::ReplyAggregator agg(cntx->reply_builder()); - - (*cntx)->StartArray(result->size()); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(result->size()); for (const auto& val : *result) { if (val) { - (*cntx)->SendBulkString(*val); + rb->SendBulkString(*val); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } } else if (result.status() == OpStatus::KEY_NOTFOUND) { SinkReplyBuilder::ReplyAggregator agg(cntx->reply_builder()); - (*cntx)->StartArray(args.size()); + rb->StartArray(args.size()); for (unsigned i = 0; i < args.size(); ++i) { - (*cntx)->SendNull(); + rb->SendNull(); } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -837,14 +839,15 @@ void HSetFamily::HGet(CmdArgList args, ConnectionContext* cntx) { return OpGet(t->GetOpArgs(shard), key, field); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendBulkString(*result); + rb->SendBulkString(*result); } else { if (result.status() == OpStatus::KEY_NOTFOUND) { - (*cntx)->SendNull(); + rb->SendNull(); } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } } @@ -856,7 +859,7 @@ void HSetFamily::HIncrBy(CmdArgList args, ConnectionContext* cntx) { int64_t ival = 0; if (!absl::SimpleAtoi(incrs, &ival)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } IncrByParam param{ival}; @@ -868,17 +871,17 @@ void HSetFamily::HIncrBy(CmdArgList args, ConnectionContext* cntx) { OpStatus status = cntx->transaction->ScheduleSingleHop(std::move(cb)); if (status == OpStatus::OK) { - (*cntx)->SendLong(get(param)); + cntx->SendLong(get(param)); } else { switch (status) { case OpStatus::INVALID_VALUE: - (*cntx)->SendError("hash value is not an integer"); + cntx->SendError("hash value is not an integer"); break; case OpStatus::OUT_OF_RANGE: - (*cntx)->SendError(kIncrOverflow); + cntx->SendError(kIncrOverflow); break; default: - (*cntx)->SendError(status); + cntx->SendError(status); break; } } @@ -891,7 +894,7 @@ void HSetFamily::HIncrByFloat(CmdArgList args, ConnectionContext* cntx) { double dval = 0; if (!absl::SimpleAtod(incrs, &dval)) { - return (*cntx)->SendError(kInvalidFloatErr); + return cntx->SendError(kInvalidFloatErr); } IncrByParam param{dval}; @@ -903,14 +906,15 @@ void HSetFamily::HIncrByFloat(CmdArgList args, ConnectionContext* cntx) { OpStatus status = cntx->transaction->ScheduleSingleHop(std::move(cb)); if (status == OpStatus::OK) { - (*cntx)->SendDouble(get(param)); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendDouble(get(param)); } else { switch (status) { case OpStatus::INVALID_VALUE: - (*cntx)->SendError("hash value is not a float"); + cntx->SendError("hash value is not a float"); break; default: - (*cntx)->SendError(status); + cntx->SendError(status); break; } } @@ -935,19 +939,19 @@ void HSetFamily::HScan(CmdArgList args, ConnectionContext* cntx) { uint64_t cursor = 0; if (!absl::SimpleAtoi(token, &cursor)) { - return (*cntx)->SendError("invalid cursor"); + return cntx->SendError("invalid cursor"); } // HSCAN key cursor [MATCH pattern] [COUNT count] if (args.size() > 6) { DVLOG(1) << "got " << args.size() << " this is more than it should be"; - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } OpResult ops = ScanOpts::TryFrom(args.subspan(2)); if (!ops) { DVLOG(1) << "HScan invalid args - return " << ops << " to the user"; - return (*cntx)->SendError(ops.status()); + return cntx->SendError(ops.status()); } ScanOpts scan_op = ops.value(); @@ -956,16 +960,17 @@ void HSetFamily::HScan(CmdArgList args, ConnectionContext* cntx) { return OpScan(t->GetOpArgs(shard), key, &cursor, scan_op); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() != OpStatus::WRONG_TYPE) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(absl::StrCat(cursor)); - (*cntx)->StartArray(result->size()); // Within scan the page type is array + rb->StartArray(2); + rb->SendBulkString(absl::StrCat(cursor)); + rb->StartArray(result->size()); // Within scan the page type is array for (const auto& k : *result) { - (*cntx)->SendBulkString(k); + rb->SendBulkString(k); } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -975,7 +980,7 @@ void HSetFamily::HSet(CmdArgList args, ConnectionContext* cntx) { string_view cmd{cntx->cid->name()}; if (args.size() % 2 != 1) { - return (*cntx)->SendError(facade::WrongNumArgsError(cmd), kSyntaxErrType); + return cntx->SendError(facade::WrongNumArgsError(cmd), kSyntaxErrType); } args.remove_prefix(1); @@ -986,9 +991,9 @@ void HSetFamily::HSet(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result && cmd == "HSET") { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1002,9 +1007,9 @@ void HSetFamily::HSetNx(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1018,9 +1023,9 @@ void HSetFamily::HStrLen(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1035,7 +1040,7 @@ void StrVecEmplaceBack(StringVec& str_vec, const listpackEntry& lp) { void HSetFamily::HRandField(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 3) { DVLOG(1) << "Wrong number of command arguments: " << args.size(); - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } string_view key = ArgS(args, 0); @@ -1043,13 +1048,13 @@ void HSetFamily::HRandField(CmdArgList args, ConnectionContext* cntx) { bool with_values = false; if ((args.size() > 1) && (!SimpleAtoi(ArgS(args, 1), &count))) { - return (*cntx)->SendError("count value is not an integer", kSyntaxErrType); + return cntx->SendError("count value is not an integer", kSyntaxErrType); } if (args.size() == 3) { ToUpper(&args[2]); if (ArgS(args, 2) != "WITHVALUES") - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); else with_values = true; } @@ -1133,13 +1138,14 @@ void HSetFamily::HRandField(CmdArgList args, ConnectionContext* cntx) { return str_vec; }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendStringArr(*result); + rb->SendStringArr(*result); } else if (result.status() == OpStatus::KEY_NOTFOUND) { - (*cntx)->SendNull(); + rb->SendNull(); } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } diff --git a/src/server/json_family.cc b/src/server/json_family.cc index f3fd94bc1..343ee514f 100644 --- a/src/server/json_family.cc +++ b/src/server/json_family.cc @@ -98,20 +98,21 @@ JsonExpression ParseJsonPath(string_view path, error_code* ec) { template void PrintOptVec(ConnectionContext* cntx, const OpResult>>& result) { + auto* rb = static_cast(cntx->reply_builder()); if (result->empty()) { - (*cntx)->SendNullArray(); + rb->SendNullArray(); } else { - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); for (auto& it : *result) { if (it.has_value()) { if constexpr (is_floating_point_v) { - (*cntx)->SendDouble(*it); + rb->SendDouble(*it); } else { static_assert(is_integral_v, "Integral required."); - (*cntx)->SendLong(*it); + rb->SendLong(*it); } } else { - (*cntx)->SendNull(); + rb->SendNull(); } } } @@ -362,30 +363,30 @@ size_t CountJsonFields(const JsonType& j) { return res; } -void SendJsonValue(ConnectionContext* cntx, const JsonType& j) { +void SendJsonValue(RedisReplyBuilder* rb, const JsonType& j) { if (j.is_double()) { - (*cntx)->SendDouble(j.as_double()); + rb->SendDouble(j.as_double()); } else if (j.is_number()) { - (*cntx)->SendLong(j.as_integer()); + rb->SendLong(j.as_integer()); } else if (j.is_bool()) { - (*cntx)->SendSimpleString(j.as_bool() ? "true" : "false"); + rb->SendSimpleString(j.as_bool() ? "true" : "false"); } else if (j.is_null()) { - (*cntx)->SendNull(); + rb->SendNull(); } else if (j.is_string()) { - (*cntx)->SendSimpleString(j.as_string_view()); + rb->SendSimpleString(j.as_string_view()); } else if (j.is_object()) { - (*cntx)->StartArray(j.size() + 1); - (*cntx)->SendSimpleString("{"); + rb->StartArray(j.size() + 1); + rb->SendSimpleString("{"); for (const auto& item : j.object_range()) { - (*cntx)->StartArray(2); - (*cntx)->SendSimpleString(item.key()); - SendJsonValue(cntx, item.value()); + rb->StartArray(2); + rb->SendSimpleString(item.key()); + SendJsonValue(rb, item.value()); } } else if (j.is_array()) { - (*cntx)->StartArray(j.size() + 1); - (*cntx)->SendSimpleString("["); + rb->StartArray(j.size() + 1); + rb->SendSimpleString("["); for (const auto& item : j.array_range()) { - SendJsonValue(cntx, item); + SendJsonValue(rb, item); } } } @@ -1146,7 +1147,7 @@ void JsonFamily::Set(CmdArgList args, ConnectionContext* cntx) { } else if (absl::EqualsIgnoreCase(operation_opts, "XX")) { is_xx_condition = true; } else { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } } @@ -1157,15 +1158,15 @@ void JsonFamily::Set(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult result = trans->ScheduleSingleHopT(move(cb)); - + auto* rb = static_cast(cntx->reply_builder()); if (result) { if (*result) { - (*cntx)->SendSimpleString("OK"); + rb->SendSimpleString("OK"); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -1181,7 +1182,7 @@ void JsonFamily::Resp(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1192,13 +1193,14 @@ void JsonFamily::Resp(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult> result = trans->ScheduleSingleHopT(move(cb)); + auto* rb = static_cast(cntx->reply_builder()); if (result) { - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); for (const auto& it : *result) { - SendJsonValue(cntx, it); + SendJsonValue(rb, it); } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -1208,22 +1210,23 @@ void JsonFamily::Debug(CmdArgList args, ConnectionContext* cntx) { // The 'MEMORY' sub-command is not supported yet, calling to operation function should be added // here. if (absl::EqualsIgnoreCase(command, "help")) { - (*cntx)->StartArray(2); - (*cntx)->SendSimpleString( + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(2); + rb->SendSimpleString( "JSON.DEBUG FIELDS - report number of fields in the JSON element."); - (*cntx)->SendSimpleString("JSON.DEBUG HELP - print help message."); + rb->SendSimpleString("JSON.DEBUG HELP - print help message."); return; } else if (absl::EqualsIgnoreCase(command, "fields")) { func = &OpFields; } else { - (*cntx)->SendError(facade::UnknownSubCmd(command, "JSON.DEBUG"), facade::kSyntaxErrType); + cntx->SendError(facade::UnknownSubCmd(command, "JSON.DEBUG"), facade::kSyntaxErrType); return; } if (args.size() < 3) { - (*cntx)->SendError(facade::WrongNumArgsError(cntx->cid->name()), facade::kSyntaxErrType); + cntx->SendError(facade::WrongNumArgsError(cntx->cid->name()), facade::kSyntaxErrType); return; } @@ -1234,7 +1237,7 @@ void JsonFamily::Debug(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1248,7 +1251,7 @@ void JsonFamily::Debug(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1261,7 +1264,7 @@ void JsonFamily::MGet(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1298,12 +1301,13 @@ void JsonFamily::MGet(CmdArgList args, ConnectionContext* cntx) { } } - (*cntx)->StartArray(results.size()); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(results.size()); for (auto& it : results) { if (!it) { - (*cntx)->SendNull(); + rb->SendNull(); } else { - (*cntx)->SendBulkString(*it); + rb->SendBulkString(*it); } } } @@ -1317,18 +1321,18 @@ void JsonFamily::ArrIndex(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } optional search_value = JsonFromString(ArgS(args, 2)); if (!search_value) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } if (search_value->is_object() || search_value->is_array()) { - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); return; } @@ -1336,7 +1340,7 @@ void JsonFamily::ArrIndex(CmdArgList args, ConnectionContext* cntx) { if (args.size() >= 4) { if (!absl::SimpleAtoi(ArgS(args, 3), &start_index)) { VLOG(1) << "Failed to convert the start index to numeric" << ArgS(args, 3); - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } } @@ -1345,7 +1349,7 @@ void JsonFamily::ArrIndex(CmdArgList args, ConnectionContext* cntx) { if (args.size() >= 5) { if (!absl::SimpleAtoi(ArgS(args, 4), &end_index)) { VLOG(1) << "Failed to convert the stop index to numeric" << ArgS(args, 4); - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } } @@ -1361,7 +1365,7 @@ void JsonFamily::ArrIndex(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1372,7 +1376,7 @@ void JsonFamily::ArrInsert(CmdArgList args, ConnectionContext* cntx) { if (!absl::SimpleAtoi(ArgS(args, 2), &index)) { VLOG(1) << "Failed to convert the following value to numeric: " << ArgS(args, 2); - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } @@ -1380,7 +1384,7 @@ void JsonFamily::ArrInsert(CmdArgList args, ConnectionContext* cntx) { for (size_t i = 3; i < args.size(); i++) { optional val = JsonFromString(ArgS(args, i)); if (!val) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1396,7 +1400,7 @@ void JsonFamily::ArrInsert(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1407,7 +1411,7 @@ void JsonFamily::ArrAppend(CmdArgList args, ConnectionContext* cntx) { for (size_t i = 2; i < args.size(); ++i) { optional converted_val = JsonFromString(ArgS(args, i)); if (!converted_val) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } append_values.emplace_back(converted_val); @@ -1422,7 +1426,7 @@ void JsonFamily::ArrAppend(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1434,18 +1438,18 @@ void JsonFamily::ArrTrim(CmdArgList args, ConnectionContext* cntx) { if (!absl::SimpleAtoi(ArgS(args, 2), &start_index)) { VLOG(1) << "Failed to parse array start index"; - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } if (!absl::SimpleAtoi(ArgS(args, 3), &stop_index)) { VLOG(1) << "Failed to parse array stop index"; - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } if (stop_index < 0) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } @@ -1458,7 +1462,7 @@ void JsonFamily::ArrTrim(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1479,7 +1483,7 @@ void JsonFamily::ArrPop(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1489,17 +1493,18 @@ void JsonFamily::ArrPop(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult> result = trans->ScheduleSingleHopT(move(cb)); + auto* rb = static_cast(cntx->reply_builder()); if (result) { - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); for (auto& it : *result) { if (!it) { - (*cntx)->SendNull(); + rb->SendNull(); } else { - (*cntx)->SendSimpleString(*it); + rb->SendSimpleString(*it); } } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -1515,9 +1520,9 @@ void JsonFamily::Clear(CmdArgList args, ConnectionContext* cntx) { OpResult result = trans->ScheduleSingleHopT(move(cb)); if (result) { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1540,7 +1545,7 @@ void JsonFamily::StrAppend(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1553,7 +1558,7 @@ void JsonFamily::ObjKeys(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1563,18 +1568,18 @@ void JsonFamily::ObjKeys(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult> result = trans->ScheduleSingleHopT(move(cb)); - + auto* rb = static_cast(cntx->reply_builder()); if (result) { - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); for (auto& it : *result) { if (it.empty()) { - (*cntx)->SendNullArray(); + rb->SendNullArray(); } else { - (*cntx)->SendStringArr(it); + rb->SendStringArr(it); } } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -1591,7 +1596,7 @@ void JsonFamily::Del(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult result = trans->ScheduleSingleHopT(move(cb)); - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } void JsonFamily::NumIncrBy(CmdArgList args, ConnectionContext* cntx) { @@ -1601,7 +1606,7 @@ void JsonFamily::NumIncrBy(CmdArgList args, ConnectionContext* cntx) { double dnum; if (!ParseDouble(num, &dnum)) { - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); return; } @@ -1613,9 +1618,9 @@ void JsonFamily::NumIncrBy(CmdArgList args, ConnectionContext* cntx) { OpResult result = trans->ScheduleSingleHopT(move(cb)); if (result) { - (*cntx)->SendSimpleString(*result); + cntx->SendSimpleString(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1626,7 +1631,7 @@ void JsonFamily::NumMultBy(CmdArgList args, ConnectionContext* cntx) { double dnum; if (!ParseDouble(num, &dnum)) { - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); return; } @@ -1638,9 +1643,9 @@ void JsonFamily::NumMultBy(CmdArgList args, ConnectionContext* cntx) { OpResult result = trans->ScheduleSingleHopT(move(cb)); if (result) { - (*cntx)->SendSimpleString(*result); + cntx->SendSimpleString(*result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1658,7 +1663,7 @@ void JsonFamily::Toggle(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1671,7 +1676,7 @@ void JsonFamily::Type(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1681,19 +1686,19 @@ void JsonFamily::Type(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult> result = trans->ScheduleSingleHopT(move(cb)); - + auto* rb = static_cast(cntx->reply_builder()); if (result) { if (result->empty()) { // When vector is empty, the path doesn't exist in the corresponding json. - (*cntx)->SendNull(); + rb->SendNull(); } else { - (*cntx)->SendStringArr(*result); + rb->SendStringArr(*result); } } else { if (result.status() == OpStatus::KEY_NOTFOUND) { - (*cntx)->SendNullArray(); + rb->SendNullArray(); } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } } @@ -1707,7 +1712,7 @@ void JsonFamily::ArrLen(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1721,7 +1726,7 @@ void JsonFamily::ArrLen(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1734,7 +1739,7 @@ void JsonFamily::ObjLen(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1748,7 +1753,7 @@ void JsonFamily::ObjLen(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1761,7 +1766,7 @@ void JsonFamily::StrLen(CmdArgList args, ConnectionContext* cntx) { if (ec) { VLOG(1) << "Invalid JSONPath syntax: " << ec.message(); - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -1775,7 +1780,7 @@ void JsonFamily::StrLen(CmdArgList args, ConnectionContext* cntx) { if (result) { PrintOptVec(cntx, result); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1812,7 +1817,7 @@ void JsonFamily::Get(CmdArgList args, ConnectionContext* cntx) { expr = ParseJsonPath(expr_str, &ec); if (ec) { LOG(WARNING) << "path '" << expr_str << "': Invalid JSONPath syntax: " << ec.message(); - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } @@ -1820,7 +1825,7 @@ void JsonFamily::Get(CmdArgList args, ConnectionContext* cntx) { } if (auto err = parser.Error(); err) - return (*cntx)->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); bool should_format = (indent || new_line || space); auto cb = [&](Transaction* t, EngineShard* shard) { @@ -1829,14 +1834,14 @@ void JsonFamily::Get(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult result = trans->ScheduleSingleHopT(move(cb)); - + auto* rb = static_cast(cntx->reply_builder()); if (result) { - (*cntx)->SendBulkString(*result); + rb->SendBulkString(*result); } else { if (result == facade::OpStatus::KEY_NOTFOUND) { - (*cntx)->SendNull(); // Match Redis + rb->SendNull(); // Match Redis } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } } diff --git a/src/server/list_family.cc b/src/server/list_family.cc index cbf91f5c9..436108e7d 100644 --- a/src/server/list_family.cc +++ b/src/server/list_family.cc @@ -754,17 +754,18 @@ void MoveGeneric(ConnectionContext* cntx, string_view src, string_view dest, Lis result = MoveTwoShards(cntx->transaction, src, dest, src_dir, dest_dir, true); } + auto* rb = static_cast(cntx->reply_builder()); if (result) { - return (*cntx)->SendBulkString(*result); + return rb->SendBulkString(*result); } switch (result.status()) { case OpStatus::KEY_NOTFOUND: - (*cntx)->SendNull(); + rb->SendNull(); break; default: - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); break; } } @@ -783,27 +784,28 @@ void BRPopLPush(CmdArgList args, ConnectionContext* cntx) { float timeout; if (!absl::SimpleAtof(timeout_str, &timeout)) { - return (*cntx)->SendError("timeout is not a float or out of range"); + return cntx->SendError("timeout is not a float or out of range"); } if (timeout < 0) { - return (*cntx)->SendError("timeout is negative"); + return cntx->SendError("timeout is negative"); } BPopPusher bpop_pusher(src, dest, ListDir::RIGHT, ListDir::LEFT); OpResult op_res = bpop_pusher.Run(cntx->transaction, unsigned(timeout * 1000)); + auto* rb = static_cast(cntx->reply_builder()); if (op_res) { - return (*cntx)->SendBulkString(*op_res); + return rb->SendBulkString(*op_res); } switch (op_res.status()) { case OpStatus::TIMED_OUT: - return (*cntx)->SendNull(); + return rb->SendNull(); break; default: - return (*cntx)->SendError(op_res.status()); + return rb->SendError(op_res.status()); break; } } @@ -815,11 +817,11 @@ void BLMove(CmdArgList args, ConnectionContext* cntx) { float timeout; if (!absl::SimpleAtof(timeout_str, &timeout)) { - return (*cntx)->SendError("timeout is not a float or out of range"); + return cntx->SendError("timeout is not a float or out of range"); } if (timeout < 0) { - return (*cntx)->SendError("timeout is negative"); + return cntx->SendError("timeout is negative"); } ToUpper(&args[2]); @@ -828,23 +830,24 @@ void BLMove(CmdArgList args, ConnectionContext* cntx) { optional src_dir = ParseDir(ArgS(args, 2)); optional dest_dir = ParseDir(ArgS(args, 3)); if (!src_dir || !dest_dir) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } BPopPusher bpop_pusher(src, dest, *src_dir, *dest_dir); OpResult op_res = bpop_pusher.Run(cntx->transaction, unsigned(timeout * 1000)); + auto* rb = static_cast(cntx->reply_builder()); if (op_res) { - return (*cntx)->SendBulkString(*op_res); + return rb->SendBulkString(*op_res); } switch (op_res.status()) { case OpStatus::TIMED_OUT: - return (*cntx)->SendNull(); + return rb->SendNull(); break; default: - return (*cntx)->SendError(op_res.status()); + return rb->SendError(op_res.status()); break; } } @@ -954,11 +957,11 @@ void ListFamily::LLen(CmdArgList args, ConnectionContext* cntx) { auto cb = [&](Transaction* t, EngineShard* shard) { return OpLen(t->GetOpArgs(shard), key); }; OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendLong(result.value()); + cntx->SendLong(result.value()); } else if (result.status() == OpStatus::KEY_NOTFOUND) { - (*cntx)->SendLong(0); + cntx->SendLong(0); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -976,18 +979,18 @@ void ListFamily::LPos(CmdArgList args, ConnectionContext* cntx) { const auto& arg_v = ArgS(args, i); if (arg_v == "RANK") { if (!absl::SimpleAtoi(ArgS(args, (i + 1)), &rank) || rank == 0) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } } if (arg_v == "COUNT") { if (!absl::SimpleAtoi(ArgS(args, (i + 1)), &count)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } skip_count = false; } if (arg_v == "MAXLEN") { if (!absl::SimpleAtoi(ArgS(args, (i + 1)), &max_len)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } } } @@ -1000,23 +1003,24 @@ void ListFamily::LPos(CmdArgList args, ConnectionContext* cntx) { OpResult> result = trans->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); } else if (result.status() == OpStatus::INVALID_VALUE) { - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); } + auto* rb = static_cast(cntx->reply_builder()); if (skip_count) { if (result->empty()) { - (*cntx)->SendNull(); + rb->SendNull(); } else { - (*cntx)->SendLong((*result)[0]); + rb->SendLong((*result)[0]); } } else { SinkReplyBuilder::ReplyAggregator agg(cntx->reply_builder()); - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); const auto& array = result.value(); for (const auto& v : array) { - (*cntx)->SendLong(v); + rb->SendLong(v); } } } @@ -1026,7 +1030,7 @@ void ListFamily::LIndex(CmdArgList args, ConnectionContext* cntx) { std::string_view index_str = ArgS(args, 1); int32_t index; if (!absl::SimpleAtoi(index_str, &index)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } @@ -1034,13 +1038,14 @@ void ListFamily::LIndex(CmdArgList args, ConnectionContext* cntx) { return OpIndex(t->GetOpArgs(shard), key, index); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendBulkString(result.value()); + rb->SendBulkString(result.value()); } else if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } @@ -1058,7 +1063,7 @@ void ListFamily::LInsert(CmdArgList args, ConnectionContext* cntx) { } else if (param == "BEFORE") { where = LIST_HEAD; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } auto cb = [&](Transaction* t, EngineShard* shard) { @@ -1067,10 +1072,10 @@ void ListFamily::LInsert(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - return (*cntx)->SendLong(result.value()); + return cntx->SendLong(result.value()); } - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } void ListFamily::LTrim(CmdArgList args, ConnectionContext* cntx) { @@ -1080,7 +1085,7 @@ void ListFamily::LTrim(CmdArgList args, ConnectionContext* cntx) { int32_t start, end; if (!absl::SimpleAtoi(s_str, &start) || !absl::SimpleAtoi(e_str, &end)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } @@ -1088,7 +1093,7 @@ void ListFamily::LTrim(CmdArgList args, ConnectionContext* cntx) { return OpTrim(t->GetOpArgs(shard), key, start, end); }; cntx->transaction->ScheduleSingleHop(std::move(cb)); - (*cntx)->SendOk(); + cntx->SendOk(); } void ListFamily::LRange(CmdArgList args, ConnectionContext* cntx) { @@ -1098,7 +1103,7 @@ void ListFamily::LRange(CmdArgList args, ConnectionContext* cntx) { int32_t start, end; if (!absl::SimpleAtoi(s_str, &start) || !absl::SimpleAtoi(e_str, &end)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } @@ -1108,10 +1113,11 @@ void ListFamily::LRange(CmdArgList args, ConnectionContext* cntx) { auto res = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (!res && res.status() != OpStatus::KEY_NOTFOUND) { - return (*cntx)->SendError(res.status()); + return cntx->SendError(res.status()); } - (*cntx)->SendStringArr(*res); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendStringArr(*res); } // lrem key 5 foo, will remove foo elements from the list if exists at most 5 times. @@ -1122,7 +1128,7 @@ void ListFamily::LRem(CmdArgList args, ConnectionContext* cntx) { int32_t count; if (!absl::SimpleAtoi(index_str, &count)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } @@ -1131,9 +1137,9 @@ void ListFamily::LRem(CmdArgList args, ConnectionContext* cntx) { }; OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendLong(result.value()); + cntx->SendLong(result.value()); } else { - (*cntx)->SendLong(0); + cntx->SendLong(0); } } @@ -1144,7 +1150,7 @@ void ListFamily::LSet(CmdArgList args, ConnectionContext* cntx) { int32_t count; if (!absl::SimpleAtoi(index_str, &count)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } @@ -1153,9 +1159,9 @@ void ListFamily::LSet(CmdArgList args, ConnectionContext* cntx) { }; OpResult result = cntx->transaction->ScheduleSingleHop(std::move(cb)); if (result) { - (*cntx)->SendOk(); + cntx->SendOk(); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1179,7 +1185,7 @@ void ListFamily::LMove(CmdArgList args, ConnectionContext* cntx) { optional src_dir = ParseDir(src_dir_str); optional dest_dir = ParseDir(dest_dir_str); if (!src_dir || !dest_dir) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } MoveGeneric(cntx, src, dest, *src_dir, *dest_dir); @@ -1191,10 +1197,10 @@ void ListFamily::BPopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cn float timeout; auto timeout_str = ArgS(args, args.size() - 1); if (!absl::SimpleAtof(timeout_str, &timeout)) { - return (*cntx)->SendError("timeout is not a float or out of range"); + return cntx->SendError("timeout is not a float or out of range"); } if (timeout < 0) { - return (*cntx)->SendError("timeout is negative"); + return cntx->SendError("timeout is negative"); } VLOG(1) << "BPop timeout(" << timeout << ")"; @@ -1209,23 +1215,24 @@ void ListFamily::BPopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cn OpResult popped_key = container_utils::RunCbOnFirstNonEmptyBlocking( transaction, OBJ_LIST, move(cb), unsigned(timeout * 1000)); cntx->conn_state.is_blocking = false; + auto* rb = static_cast(cntx->reply_builder()); if (popped_key) { DVLOG(1) << "BPop " << transaction->DebugId() << " popped from key " << popped_key; // key. std::string_view str_arr[2] = {*popped_key, popped_value}; - return (*cntx)->SendStringArr(str_arr); + return rb->SendStringArr(str_arr); } DVLOG(1) << "result for " << transaction->DebugId() << " is " << popped_key.status(); switch (popped_key.status()) { case OpStatus::WRONG_TYPE: - return (*cntx)->SendError(kWrongTypeErr); + return rb->SendError(kWrongTypeErr); case OpStatus::TIMED_OUT: - return (*cntx)->SendNullArray(); + return rb->SendNullArray(); default: LOG(ERROR) << "Unexpected error " << popped_key.status(); } - return (*cntx)->SendNullArray(); + return rb->SendNullArray(); } void ListFamily::PushGeneric(ListDir dir, bool skip_notexists, CmdArgList args, @@ -1242,10 +1249,10 @@ void ListFamily::PushGeneric(ListDir dir, bool skip_notexists, CmdArgList args, OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - return (*cntx)->SendLong(result.value()); + return cntx->SendLong(result.value()); } - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); } void ListFamily::PopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cntx) { @@ -1255,16 +1262,16 @@ void ListFamily::PopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cnt if (args.size() > 1) { if (args.size() > 2) { - return (*cntx)->SendError(WrongNumArgsError(cntx->cid->name())); + return cntx->SendError(WrongNumArgsError(cntx->cid->name())); } string_view count_s = ArgS(args, 1); if (!absl::SimpleAtoi(count_s, &count)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (count < 0) { - return (*cntx)->SendError(kUintErr); + return cntx->SendError(kUintErr); } return_arr = true; } @@ -1274,27 +1281,27 @@ void ListFamily::PopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cnt }; OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); - + auto* rb = static_cast(cntx->reply_builder()); switch (result.status()) { case OpStatus::KEY_NOTFOUND: - return (*cntx)->SendNull(); + return rb->SendNull(); case OpStatus::WRONG_TYPE: - return (*cntx)->SendError(kWrongTypeErr); + return rb->SendError(kWrongTypeErr); default:; } if (return_arr) { if (result->empty()) { - (*cntx)->SendNullArray(); + rb->SendNullArray(); } else { - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); for (const auto& k : *result) { - (*cntx)->SendBulkString(k); + rb->SendBulkString(k); } } } else { DCHECK_EQ(1u, result->size()); - (*cntx)->SendBulkString(result->front()); + rb->SendBulkString(result->front()); } } diff --git a/src/server/main_service.cc b/src/server/main_service.cc index 9057ca66b..23a14bcc8 100644 --- a/src/server/main_service.cc +++ b/src/server/main_service.cc @@ -1115,7 +1115,7 @@ void Service::DispatchCommand(CmdArgList args, facade::ConnectionContext* cntx) dfly_cntx->transaction->InitByArgs(dfly_cntx->conn_state.db_index, args_no_cmd); if (status != OpStatus::OK) - return (*cntx)->SendError(status); + return cntx->SendError(status); } } else { DCHECK(dfly_cntx->transaction == nullptr); @@ -1126,7 +1126,7 @@ void Service::DispatchCommand(CmdArgList args, facade::ConnectionContext* cntx) if (!dist_trans->IsMulti()) { // Multi command initialize themself based on their mode. if (auto st = dist_trans->InitByArgs(dfly_cntx->conn_state.db_index, args_no_cmd); st != OpStatus::OK) - return (*cntx)->SendError(st); + return cntx->SendError(st); } dfly_cntx->transaction = dist_trans.get(); @@ -1184,7 +1184,7 @@ bool Service::InvokeCmd(const CommandId* cid, CmdArgList tail_args, ConnectionCo DCHECK(!cid->Validate(tail_args)); if (auto err = VerifyCommandExecution(cid, cntx); err) { - (*cntx)->SendError(std::move(*err)); + cntx->SendError(std::move(*err)); return true; // return false only for internal error aborts } @@ -1462,7 +1462,7 @@ absl::flat_hash_map Service::UknownCmdMap() const { void Service::Quit(CmdArgList args, ConnectionContext* cntx) { if (cntx->protocol() == facade::Protocol::REDIS) - (*cntx)->SendOk(); + cntx->SendOk(); using facade::SinkReplyBuilder; SinkReplyBuilder* builder = cntx->reply_builder(); @@ -1474,11 +1474,11 @@ void Service::Quit(CmdArgList args, ConnectionContext* cntx) { void Service::Multi(CmdArgList args, ConnectionContext* cntx) { if (cntx->conn_state.exec_info.IsCollecting()) { - return (*cntx)->SendError("MULTI calls can not be nested"); + return cntx->SendError("MULTI calls can not be nested"); } cntx->conn_state.exec_info.state = ConnectionState::ExecInfo::EXEC_COLLECT; // TODO: to protect against huge exec transactions. - return (*cntx)->SendOk(); + return cntx->SendOk(); } void Service::Watch(CmdArgList args, ConnectionContext* cntx) { @@ -1486,7 +1486,7 @@ void Service::Watch(CmdArgList args, ConnectionContext* cntx) { // Skip if EXEC will already fail due previous WATCH. if (exec_info.watched_dirty.load(memory_order_relaxed)) { - return (*cntx)->SendOk(); + return cntx->SendOk(); } atomic_uint32_t keys_existed = 0; @@ -1508,12 +1508,12 @@ void Service::Watch(CmdArgList args, ConnectionContext* cntx) { exec_info.watched_keys.emplace_back(cntx->db_index(), ArgS(args, i)); } - return (*cntx)->SendOk(); + return cntx->SendOk(); } void Service::Unwatch(CmdArgList args, ConnectionContext* cntx) { UnwatchAllKeys(cntx); - return (*cntx)->SendOk(); + return cntx->SendOk(); } template void WithReplies(CapturingReplyBuilder* crb, ConnectionContext* cntx, F&& f) { @@ -1593,14 +1593,15 @@ void Service::CallFromScript(ConnectionContext* cntx, Interpreter::CallArgs& ca) void Service::Eval(CmdArgList args, ConnectionContext* cntx) { string_view body = ArgS(args, 0); + auto* rb = static_cast(cntx->reply_builder()); if (body.empty()) { - return (*cntx)->SendNull(); + return rb->SendNull(); } BorrowedInterpreter interpreter{cntx}; auto res = server_family_.script_mgr()->Insert(body, interpreter); if (!res) - return (*cntx)->SendError(res.error().Format(), facade::kScriptErrType); + return rb->SendError(res.error().Format(), facade::kScriptErrType); string sha{std::move(res.value())}; @@ -1677,7 +1678,7 @@ optional StartMultiEval(DbIndex dbid, CmdArgList keys, ScriptMgr::ScriptPa string err = StrCat( "Multi mode conflict when running eval in multi transaction. Multi mode is: ", multi_mode, " eval mode is: ", script_mode); - (*cntx)->SendError(err); + cntx->SendError(err); return nullopt; } return false; @@ -1758,12 +1759,12 @@ void Service::EvalInternal(CmdArgList args, const EvalArgs& eval_args, Interpret // Sanitizing the input to avoid code injection. if (eval_args.sha.size() != 40 || !IsSHA(eval_args.sha)) { - return (*cntx)->SendError(facade::kScriptNotFound); + return cntx->SendError(facade::kScriptNotFound); } auto params = LoadScipt(eval_args.sha, server_family_.script_mgr(), interpreter); if (!params) - return (*cntx)->SendError(facade::kScriptNotFound); + return cntx->SendError(facade::kScriptNotFound); string error; @@ -1854,7 +1855,7 @@ void Service::EvalInternal(CmdArgList args, const EvalArgs& eval_args, Interpret if (result == Interpreter::RUN_ERR) { string resp = StrCat("Error running script (call to ", eval_args.sha, "): ", error); - return (*cntx)->SendError(resp, facade::kScriptErrType); + return cntx->SendError(resp, facade::kScriptErrType); } CHECK(result == Interpreter::RUN_OK); @@ -1862,14 +1863,14 @@ void Service::EvalInternal(CmdArgList args, const EvalArgs& eval_args, Interpret SinkReplyBuilder::ReplyAggregator agg(cntx->reply_builder()); EvalSerializer ser{static_cast(cntx->reply_builder())}; if (!interpreter->IsResultSafe()) { - (*cntx)->SendError("reached lua stack limit"); + cntx->SendError("reached lua stack limit"); } else { interpreter->SerializeResult(&ser); } } void Service::Discard(CmdArgList args, ConnectionContext* cntx) { - RedisReplyBuilder* rb = (*cntx).operator->(); + auto* rb = static_cast(cntx->reply_builder()); if (!cntx->conn_state.exec_info.IsCollecting()) { return rb->SendError("DISCARD without MULTI"); @@ -1976,7 +1977,7 @@ void StartMultiExec(DbIndex dbid, Transaction* trans, ConnectionState::ExecInfo* } void Service::Exec(CmdArgList args, ConnectionContext* cntx) { - RedisReplyBuilder* rb = (*cntx).operator->(); + auto* rb = static_cast(cntx->reply_builder()); absl::Cleanup exec_clear = [&cntx] { MultiCleanup(cntx); }; @@ -2047,7 +2048,7 @@ void Service::Exec(CmdArgList args, ConnectionContext* cntx) { if (scmd.Cid()->IsTransactional()) { OpStatus st = cntx->transaction->InitByArgs(cntx->conn_state.db_index, args); if (st != OpStatus::OK) { - (*cntx)->SendError(st); + cntx->SendError(st); break; } } @@ -2120,7 +2121,7 @@ void Service::Publish(CmdArgList args, ConnectionContext* cntx) { shard_set->pool()->DispatchBrief(std::move(cb)); } - (*cntx)->SendLong(num_published); + cntx->SendLong(num_published); } void Service::Subscribe(CmdArgList args, ConnectionContext* cntx) { @@ -2154,34 +2155,35 @@ void Service::Function(CmdArgList args, ConnectionContext* cntx) { string_view sub_cmd = ArgS(args, 0); if (sub_cmd == "FLUSH") { - return (*cntx)->SendOk(); + return cntx->SendOk(); } string err = UnknownSubCmd(sub_cmd, "FUNCTION"); - return (*cntx)->SendError(err, kSyntaxErrType); + return cntx->SendError(err, kSyntaxErrType); } void Service::PubsubChannels(string_view pattern, ConnectionContext* cntx) { - (*cntx)->SendStringArr(ServerState::tlocal()->channel_store()->ListChannels(pattern)); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendStringArr(ServerState::tlocal()->channel_store()->ListChannels(pattern)); } void Service::PubsubPatterns(ConnectionContext* cntx) { size_t pattern_count = ServerState::tlocal()->channel_store()->PatternCount(); - (*cntx)->SendLong(pattern_count); + cntx->SendLong(pattern_count); } void Service::Monitor(CmdArgList args, ConnectionContext* cntx) { VLOG(1) << "starting monitor on this connection: " << cntx->conn()->GetClientId(); // we are registering the current connection for all threads so they will be aware of // this connection, to send to it any command - (*cntx)->SendOk(); + cntx->SendOk(); cntx->ChangeMonitor(true /* start */); } void Service::Pubsub(CmdArgList args, ConnectionContext* cntx) { if (args.size() < 1) { - (*cntx)->SendError(WrongNumArgsError(cntx->cid->name())); + cntx->SendError(WrongNumArgsError(cntx->cid->name())); return; } @@ -2198,7 +2200,8 @@ void Service::Pubsub(CmdArgList args, ConnectionContext* cntx) { "HELP", "\tPrints this help."}; - (*cntx)->SendSimpleStrArr(help_arr); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendSimpleStrArr(help_arr); return; } @@ -2212,7 +2215,7 @@ void Service::Pubsub(CmdArgList args, ConnectionContext* cntx) { } else if (subcmd == "NUMPAT") { PubsubPatterns(cntx); } else { - (*cntx)->SendError(UnknownSubCmd(subcmd, "PUBSUB")); + cntx->SendError(UnknownSubCmd(subcmd, "PUBSUB")); } } @@ -2224,28 +2227,29 @@ void Service::Command(CmdArgList args, ConnectionContext* cntx) { } }); - auto serialize_command = [&cntx](string_view name, const CommandId& cid) { - (*cntx)->StartArray(6); - (*cntx)->SendSimpleString(cid.name()); - (*cntx)->SendLong(cid.arity()); - (*cntx)->StartArray(CommandId::OptCount(cid.opt_mask())); + auto* rb = static_cast(cntx->reply_builder()); + auto serialize_command = [&rb](string_view name, const CommandId& cid) { + rb->StartArray(6); + rb->SendSimpleString(cid.name()); + rb->SendLong(cid.arity()); + rb->StartArray(CommandId::OptCount(cid.opt_mask())); for (uint32_t i = 0; i < 32; ++i) { unsigned obit = (1u << i); if (cid.opt_mask() & obit) { const char* name = CO::OptName(CO::CommandOpt{obit}); - (*cntx)->SendSimpleString(name); + rb->SendSimpleString(name); } } - (*cntx)->SendLong(cid.first_key_pos()); - (*cntx)->SendLong(cid.last_key_pos()); - (*cntx)->SendLong(cid.opt_mask() & CO::INTERLEAVED_KEYS ? 2 : 1); + rb->SendLong(cid.first_key_pos()); + rb->SendLong(cid.last_key_pos()); + rb->SendLong(cid.opt_mask() & CO::INTERLEAVED_KEYS ? 2 : 1); }; // If no arguments are specified, reply with all commands if (args.empty()) { - (*cntx)->StartArray(cmd_cnt); + rb->StartArray(cmd_cnt); registry_.Traverse([&](string_view name, const CommandId& cid) { if (cid.opt_mask() & CO::HIDDEN) return; @@ -2259,7 +2263,7 @@ void Service::Command(CmdArgList args, ConnectionContext* cntx) { // COUNT if (subcmd == "COUNT") { - return (*cntx)->SendLong(cmd_cnt); + return cntx->SendLong(cmd_cnt); } // INFO [cmd] @@ -2268,16 +2272,16 @@ void Service::Command(CmdArgList args, ConnectionContext* cntx) { string_view cmd = ArgS(args, 1); if (const auto* cid = registry_.Find(cmd); cid) { - (*cntx)->StartArray(1); + rb->StartArray(1); serialize_command(cmd, *cid); } else { - (*cntx)->SendNull(); + rb->SendNull(); } return; } - return (*cntx)->SendError(kSyntaxErr, kSyntaxErrType); + return cntx->SendError(kSyntaxErr, kSyntaxErrType); } VarzValue::Map Service::GetVarzStats() { diff --git a/src/server/memory_cmd.cc b/src/server/memory_cmd.cc index ab6990c42..ff21b053c 100644 --- a/src/server/memory_cmd.cc +++ b/src/server/memory_cmd.cc @@ -99,7 +99,8 @@ void MemoryCmd::Run(CmdArgList args) { "DECOMMIT", " Force decommit the memory freed by the server back to OS.", }; - return (*cntx_)->SendSimpleStrArr(help_arr); + auto* rb = static_cast(cntx_->reply_builder()); + return rb->SendSimpleStrArr(help_arr); }; if (sub_cmd == "STATS") { @@ -116,7 +117,7 @@ void MemoryCmd::Run(CmdArgList args) { mi_heap_collect(ServerState::tlocal()->data_heap(), true); mi_heap_collect(mi_heap_get_backing(), true); }); - return (*cntx_)->SendSimpleString("OK"); + return cntx_->SendSimpleString("OK"); } if (sub_cmd == "MALLOC-STATS") { @@ -132,7 +133,7 @@ void MemoryCmd::Run(CmdArgList args) { } if (args.size() > tid_indx && !absl::SimpleAtoi(ArgS(args, tid_indx), &tid)) { - return (*cntx_)->SendError(kInvalidIntErr); + return cntx_->SendError(kInvalidIntErr); } } @@ -147,11 +148,12 @@ void MemoryCmd::Run(CmdArgList args) { string res = shard_set->pool()->at(tid)->AwaitBrief([=] { return MallocStats(backing, tid); }); - return (*cntx_)->SendBulkString(res); + auto* rb = static_cast(cntx_->reply_builder()); + return rb->SendBulkString(res); } string err = UnknownSubCmd(sub_cmd, "MEMORY"); - return (*cntx_)->SendError(err, kSyntaxErrType); + return cntx_->SendError(err, kSyntaxErrType); } namespace { @@ -270,10 +272,11 @@ void MemoryCmd::Stats() { // Serialization stats, including both replication-related serialization and saving to RDB files. stats.push_back({"serialization", serialization_memory.load()}); - (*cntx_)->StartCollection(stats.size(), RedisReplyBuilder::MAP); + auto* rb = static_cast(cntx_->reply_builder()); + rb->StartCollection(stats.size(), RedisReplyBuilder::MAP); for (const auto& [k, v] : stats) { - (*cntx_)->SendBulkString(k); - (*cntx_)->SendLong(v); + rb->SendBulkString(k); + rb->SendLong(v); } } @@ -292,7 +295,7 @@ void MemoryCmd::Usage(std::string_view key) { if (memory_usage < 0) return cntx_->SendError(kKeyNotFoundErr); - (*cntx_)->SendLong(memory_usage); + cntx_->SendLong(memory_usage); } } // namespace dfly diff --git a/src/server/multi_command_squasher.cc b/src/server/multi_command_squasher.cc index 2392feb0e..973da25b2 100644 --- a/src/server/multi_command_squasher.cc +++ b/src/server/multi_command_squasher.cc @@ -118,7 +118,7 @@ bool MultiCommandSquasher::ExecuteStandalone(StoredCmd* cmd) { if (verify_commands_) { if (auto err = service_->VerifyCommandState(cmd->Cid(), args, *cntx_); err) { - (*cntx_)->SendError(move(*err)); + cntx_->SendError(move(*err)); return !error_abort_; } } diff --git a/src/server/replica.cc b/src/server/replica.cc index f4f629d7c..e4b5dac28 100644 --- a/src/server/replica.cc +++ b/src/server/replica.cc @@ -84,11 +84,11 @@ error_code Replica::Start(ConnectionContext* cntx) { auto check_connection_error = [this, &cntx](error_code ec, const char* msg) -> error_code { if (cntx_.IsCancelled()) { - (*cntx)->SendError("replication cancelled"); + cntx->SendError("replication cancelled"); return std::make_error_code(errc::operation_canceled); } if (ec) { - (*cntx)->SendError(absl::StrCat(msg, ec.message())); + cntx->SendError(absl::StrCat(msg, ec.message())); cntx_.Cancel(); } return ec; @@ -118,7 +118,7 @@ error_code Replica::Start(ConnectionContext* cntx) { // 4. Spawn main coordination fiber. sync_fb_ = fb2::Fiber("main_replication", &Replica::MainReplicationFb, this); - (*cntx)->SendOk(); + cntx->SendOk(); return {}; } @@ -128,7 +128,7 @@ void Replica::EnableReplication(ConnectionContext* cntx) { state_mask_.store(R_ENABLED); // set replica state to enabled sync_fb_ = MakeFiber(&Replica::MainReplicationFb, this); // call replication fiber - (*cntx)->SendOk(); + cntx->SendOk(); } void Replica::Stop() { diff --git a/src/server/script_mgr.cc b/src/server/script_mgr.cc index fc57f1ea1..ef91c653b 100644 --- a/src/server/script_mgr.cc +++ b/src/server/script_mgr.cc @@ -76,7 +76,8 @@ void ScriptMgr::Run(CmdArgList args, ConnectionContext* cntx) { " Prints latency histograms in usec for every called function.", "HELP" " Prints this help."}; - return (*cntx)->SendSimpleStrArr(kHelp); + auto rb = static_cast(cntx->reply_builder()); + return rb->SendSimpleStrArr(kHelp); } if (subcmd == "EXISTS" && args.size() > 1) @@ -96,7 +97,7 @@ void ScriptMgr::Run(CmdArgList args, ConnectionContext* cntx) { string err = absl::StrCat("Unknown subcommand or wrong number of arguments for '", subcmd, "'. Try SCRIPT HELP."); - cntx->reply_builder()->SendError(err, kSyntaxErrType); + cntx->SendError(err, kSyntaxErrType); } void ScriptMgr::ExistsCmd(CmdArgList args, ConnectionContext* cntx) const { @@ -107,20 +108,21 @@ void ScriptMgr::ExistsCmd(CmdArgList args, ConnectionContext* cntx) const { } } - (*cntx)->StartArray(res.size()); + auto rb = static_cast(cntx->reply_builder()); + rb->StartArray(res.size()); for (uint8_t v : res) { - (*cntx)->SendLong(v); + rb->SendLong(v); } return; } void ScriptMgr::LoadCmd(CmdArgList args, ConnectionContext* cntx) { string_view body = ArgS(args, 1); - + auto rb = static_cast(cntx->reply_builder()); if (body.empty()) { char sha[41]; Interpreter::FuncSha1(body, sha); - return (*cntx)->SendBulkString(sha); + return rb->SendBulkString(sha); } ServerState* ss = ServerState::tlocal(); @@ -129,12 +131,12 @@ void ScriptMgr::LoadCmd(CmdArgList args, ConnectionContext* cntx) { auto res = Insert(body, interpreter); if (!res) - return (*cntx)->SendError(res.error().Format()); + return rb->SendError(res.error().Format()); // Schedule empty callback inorder to journal command via transaction framework. cntx->transaction->ScheduleSingleHop([](auto* t, auto* shard) { return OpStatus::OK; }); - return (*cntx)->SendBulkString(res.value()); + return rb->SendBulkString(res.value()); } void ScriptMgr::ConfigCmd(CmdArgList args, ConnectionContext* cntx) { @@ -144,7 +146,7 @@ void ScriptMgr::ConfigCmd(CmdArgList args, ConnectionContext* cntx) { for (auto flag : args.subspan(2)) { if (auto err = ScriptParams::ApplyFlags(facade::ToSV(flag), &data); err) - return (*cntx)->SendError("Invalid config format: " + err.Format()); + return cntx->SendError("Invalid config format: " + err.Format()); } UpdateScriptCaches(key, data); @@ -152,18 +154,19 @@ void ScriptMgr::ConfigCmd(CmdArgList args, ConnectionContext* cntx) { // Schedule empty callback inorder to journal command via transaction framework. cntx->transaction->ScheduleSingleHop([](auto* t, auto* shard) { return OpStatus::OK; }); - return (*cntx)->SendOk(); + return cntx->SendOk(); } void ScriptMgr::ListCmd(ConnectionContext* cntx) const { vector> scripts = GetAll(); - (*cntx)->StartArray(scripts.size()); + auto rb = static_cast(cntx->reply_builder()); + rb->StartArray(scripts.size()); for (const auto& [sha, data] : scripts) { - (*cntx)->StartArray(data.orig_body.empty() ? 2 : 3); - (*cntx)->SendBulkString(sha); - (*cntx)->SendBulkString(data.body); + rb->StartArray(data.orig_body.empty() ? 2 : 3); + rb->SendBulkString(sha); + rb->SendBulkString(data.body); if (!data.orig_body.empty()) - (*cntx)->SendBulkString(data.orig_body); + rb->SendBulkString(data.orig_body); } } @@ -180,11 +183,12 @@ void ScriptMgr::LatencyCmd(ConnectionContext* cntx) const { mu.unlock(); }); - (*cntx)->StartArray(result.size()); + auto rb = static_cast(cntx->reply_builder()); + rb->StartArray(result.size()); for (const auto& k_v : result) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(k_v.first); - (*cntx)->SendBulkString(k_v.second.ToString()); + rb->StartArray(2); + rb->SendBulkString(k_v.first); + rb->SendBulkString(k_v.second.ToString()); } } diff --git a/src/server/search/search_family.cc b/src/server/search/search_family.cc index 13da60b9e..c22520bd4 100644 --- a/src/server/search/search_family.cc +++ b/src/server/search/search_family.cc @@ -91,7 +91,7 @@ optional ParseSchemaOrReply(DocIndex::DataType type, CmdArgParse // Verify json path is correct if (type == DocIndex::JSON && !IsValidJsonPath(field)) { - (*cntx)->SendError("Bad json path: " + string{field}); + cntx->SendError("Bad json path: " + string{field}); return nullopt; } @@ -105,7 +105,7 @@ optional ParseSchemaOrReply(DocIndex::DataType type, CmdArgParse string_view type_str = parser.Next(); auto type = ParseSearchFieldType(type_str); if (!type) { - (*cntx)->SendError("Invalid field type: " + string{type_str}); + cntx->SendError("Invalid field type: " + string{type_str}); return nullopt; } @@ -114,7 +114,7 @@ optional ParseSchemaOrReply(DocIndex::DataType type, CmdArgParse if (*type == search::SchemaField::VECTOR) { auto vector_params = ParseVectorParams(&parser); if (!parser.HasError() && vector_params.dim == 0) { - (*cntx)->SendError("Knn vector dimension cannot be zero"); + cntx->SendError("Knn vector dimension cannot be zero"); return nullopt; } params = std::move(vector_params); @@ -148,7 +148,7 @@ optional ParseSchemaOrReply(DocIndex::DataType type, CmdArgParse schema.field_names[field_info.short_name] = field_ident; if (auto err = parser.Error(); err) { - (*cntx)->SendError(err->MakeReply()); + cntx->SendError(err->MakeReply()); return nullopt; } @@ -206,7 +206,7 @@ optional ParseSearchParamsOrReply(CmdArgParser parser, ConnectionC } if (auto err = parser.Error(); err) { - (*cntx)->SendError(err->MakeReply()); + cntx->SendError(err->MakeReply()); return nullopt; } @@ -214,11 +214,12 @@ optional ParseSearchParamsOrReply(CmdArgParser parser, ConnectionC } void SendSerializedDoc(const SerializedSearchDoc& doc, ConnectionContext* cntx) { - (*cntx)->SendBulkString(doc.key); - (*cntx)->StartCollection(doc.values.size(), RedisReplyBuilder::MAP); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendBulkString(doc.key); + rb->StartCollection(doc.values.size(), RedisReplyBuilder::MAP); for (const auto& [k, v] : doc.values) { - (*cntx)->SendBulkString(k); - (*cntx)->SendBulkString(v); + rb->SendBulkString(k); + rb->SendBulkString(v); } } @@ -236,8 +237,9 @@ void ReplyWithResults(const SearchParams& params, absl::Span resul bool ids_only = params.IdsOnly(); size_t reply_size = ids_only ? (result_count + 1) : (result_count * 2 + 1); - (*cntx)->StartArray(reply_size); - (*cntx)->SendLong(total_count); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(reply_size); + rb->SendLong(total_count); size_t sent = 0; size_t to_skip = params.limit_offset; @@ -253,7 +255,7 @@ void ReplyWithResults(const SearchParams& params, absl::Span resul return; if (ids_only) - (*cntx)->SendBulkString(serialized_doc.key); + rb->SendBulkString(serialized_doc.key); else SendSerializedDoc(serialized_doc, cntx); } @@ -291,12 +293,12 @@ void ReplySorted(search::AggregationInfo agg, const SearchParams& params, agg.alias = ""; facade::SinkReplyBuilder::ReplyAggregator agg_reply{cntx->reply_builder()}; - - (*cntx)->StartArray(reply_size); - (*cntx)->SendLong(min(total, agg_limit)); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(reply_size); + rb->SendLong(min(total, agg_limit)); for (auto* doc : absl::MakeSpan(docs).subspan(start_idx, result_count)) { if (ids_only) { - (*cntx)->SendBulkString(doc->key); + rb->SendBulkString(doc->key); continue; } @@ -325,7 +327,7 @@ void SearchFamily::FtCreate(CmdArgList args, ConnectionContext* cntx) { // PREFIX count prefix [prefix ...] if (parser.Check("PREFIX").ExpectTail(2)) { if (size_t num = parser.Next(); num != 1) - return (*cntx)->SendError("Multiple prefixes are not supported"); + return cntx->SendError("Multiple prefixes are not supported"); index.prefix = string(parser.Next()); continue; } @@ -344,7 +346,7 @@ void SearchFamily::FtCreate(CmdArgList args, ConnectionContext* cntx) { } if (auto err = parser.Error(); err) - return (*cntx)->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); cntx->transaction->Schedule(); @@ -362,7 +364,7 @@ void SearchFamily::FtCreate(CmdArgList args, ConnectionContext* cntx) { if (exists_cnt.load(memory_order_relaxed) > 0) { cntx->transaction->Conclude(); - return (*cntx)->SendError("Index already exists"); + return cntx->SendError("Index already exists"); } auto idx_ptr = make_shared(move(index)); @@ -373,7 +375,7 @@ void SearchFamily::FtCreate(CmdArgList args, ConnectionContext* cntx) { }, true); - (*cntx)->SendOk(); + cntx->SendOk(); } void SearchFamily::FtDropIndex(CmdArgList args, ConnectionContext* cntx) { @@ -389,8 +391,8 @@ void SearchFamily::FtDropIndex(CmdArgList args, ConnectionContext* cntx) { DCHECK(num_deleted == 0u || num_deleted == shard_set->size()); if (num_deleted == 0u) - return (*cntx)->SendError("-Unknown Index name"); - return (*cntx)->SendOk(); + return cntx->SendError("-Unknown Index name"); + return cntx->SendOk(); } void SearchFamily::FtInfo(CmdArgList args, ConnectionContext* cntx) { @@ -411,7 +413,7 @@ void SearchFamily::FtInfo(CmdArgList args, ConnectionContext* cntx) { DCHECK(num_notfound == 0u || num_notfound == shard_set->size()); if (num_notfound > 0u) - return (*cntx)->SendError("Unknown Index name"); + return cntx->SendError("Unknown Index name"); DCHECK(infos.front().base_index.schema.fields.size() == infos.back().base_index.schema.fields.size()); @@ -423,22 +425,23 @@ void SearchFamily::FtInfo(CmdArgList args, ConnectionContext* cntx) { const auto& info = infos.front(); const auto& schema = info.base_index.schema; - (*cntx)->StartCollection(4, RedisReplyBuilder::MAP); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartCollection(4, RedisReplyBuilder::MAP); - (*cntx)->SendSimpleString("index_name"); - (*cntx)->SendSimpleString(idx_name); + rb->SendSimpleString("index_name"); + rb->SendSimpleString(idx_name); - (*cntx)->SendSimpleString("index_definition"); + rb->SendSimpleString("index_definition"); { - (*cntx)->StartCollection(2, RedisReplyBuilder::MAP); - (*cntx)->SendSimpleString("key_type"); - (*cntx)->SendSimpleString(info.base_index.type == DocIndex::JSON ? "JSON" : "HASH"); - (*cntx)->SendSimpleString("prefix"); - (*cntx)->SendSimpleString(info.base_index.prefix); + rb->StartCollection(2, RedisReplyBuilder::MAP); + rb->SendSimpleString("key_type"); + rb->SendSimpleString(info.base_index.type == DocIndex::JSON ? "JSON" : "HASH"); + rb->SendSimpleString("prefix"); + rb->SendSimpleString(info.base_index.prefix); } - (*cntx)->SendSimpleString("attributes"); - (*cntx)->StartArray(schema.fields.size()); + rb->SendSimpleString("attributes"); + rb->StartArray(schema.fields.size()); for (const auto& [field_ident, field_info] : schema.fields) { vector info; @@ -453,11 +456,11 @@ void SearchFamily::FtInfo(CmdArgList args, ConnectionContext* cntx) { if (field_info.flags & search::SchemaField::SORTABLE) info.push_back("SORTABLE"); - (*cntx)->SendSimpleStrArr(info); + rb->SendSimpleStrArr(info); } - (*cntx)->SendSimpleString("num_docs"); - (*cntx)->SendLong(total_num_docs); + rb->SendSimpleString("num_docs"); + rb->SendLong(total_num_docs); } void SearchFamily::FtList(CmdArgList args, ConnectionContext* cntx) { @@ -470,8 +473,8 @@ void SearchFamily::FtList(CmdArgList args, ConnectionContext* cntx) { names = es->search_indices()->GetIndexNames(); return OpStatus::OK; }); - - (*cntx)->SendStringArr(names); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendStringArr(names); } void SearchFamily::FtSearch(CmdArgList args, ConnectionContext* cntx) { @@ -485,7 +488,7 @@ void SearchFamily::FtSearch(CmdArgList args, ConnectionContext* cntx) { search::SearchAlgorithm search_algo; search::SortOption* sort_opt = params->sort_option.has_value() ? &*params->sort_option : nullptr; if (!search_algo.Init(query_str, ¶ms->query_params, sort_opt)) - return (*cntx)->SendError("Query syntax error"); + return cntx->SendError("Query syntax error"); // Because our coordinator thread may not have a shard, we can't check ahead if the index exists. atomic index_not_found{false}; @@ -500,11 +503,11 @@ void SearchFamily::FtSearch(CmdArgList args, ConnectionContext* cntx) { }); if (index_not_found.load()) - return (*cntx)->SendError(string{index_name} + ": no such index"); + return cntx->SendError(string{index_name} + ": no such index"); for (const auto& res : docs) { if (res.error) - return (*cntx)->SendError(std::move(*res.error)); + return cntx->SendError(*res.error); } if (auto agg = search_algo.HasAggregation(); agg) @@ -524,7 +527,7 @@ void SearchFamily::FtProfile(CmdArgList args, ConnectionContext* cntx) { search::SearchAlgorithm search_algo; search::SortOption* sort_opt = params->sort_option.has_value() ? &*params->sort_option : nullptr; if (!search_algo.Init(query_str, ¶ms->query_params, sort_opt)) - return (*cntx)->SendError("Query syntax error"); + return cntx->SendError("Query syntax error"); search_algo.EnableProfiling(); @@ -552,24 +555,24 @@ void SearchFamily::FtProfile(CmdArgList args, ConnectionContext* cntx) { }); auto took = absl::Now() - start; - - (*cntx)->StartArray(results.size() + 1); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(results.size() + 1); // General stats - (*cntx)->StartCollection(3, RedisReplyBuilder::MAP); - (*cntx)->SendBulkString("took"); - (*cntx)->SendLong(absl::ToInt64Microseconds(took)); - (*cntx)->SendBulkString("hits"); - (*cntx)->SendLong(total_docs); - (*cntx)->SendBulkString("serialized"); - (*cntx)->SendLong(total_serialized); + rb->StartCollection(3, RedisReplyBuilder::MAP); + rb->SendBulkString("took"); + rb->SendLong(absl::ToInt64Microseconds(took)); + rb->SendBulkString("hits"); + rb->SendLong(total_docs); + rb->SendBulkString("serialized"); + rb->SendLong(total_serialized); // Per-shard stats for (const auto& [profile, shard_took] : results) { - (*cntx)->StartCollection(2, RedisReplyBuilder::MAP); - (*cntx)->SendBulkString("took"); - (*cntx)->SendLong(absl::ToInt64Microseconds(shard_took)); - (*cntx)->SendBulkString("tree"); + rb->StartCollection(2, RedisReplyBuilder::MAP); + rb->SendBulkString("took"); + rb->SendLong(absl::ToInt64Microseconds(shard_took)); + rb->SendBulkString("tree"); for (size_t i = 0; i < profile.events.size(); i++) { const auto& event = profile.events[i]; @@ -583,13 +586,13 @@ void SearchFamily::FtProfile(CmdArgList args, ConnectionContext* cntx) { } if (children > 0) - (*cntx)->StartArray(2); + rb->StartArray(2); - (*cntx)->SendSimpleString( + rb->SendSimpleString( absl::StrFormat("t=%-10u n=%-10u %s", event.micros, event.num_processed, event.descr)); if (children > 0) - (*cntx)->StartArray(children); + rb->StartArray(children); } } } diff --git a/src/server/server_family.cc b/src/server/server_family.cc index 288ec206f..127c31fd4 100644 --- a/src/server/server_family.cc +++ b/src/server/server_family.cc @@ -207,13 +207,13 @@ void SlowLogGet(dfly::CmdArgList args, dfly::ConnectionContext* cntx, dfly::Serv size_t requested_slow_log_length = UINT32_MAX; size_t argc = args.size(); if (argc >= 3) { - (*cntx)->SendError(facade::UnknownSubCmd(sub_cmd, "SLOWLOG"), facade::kSyntaxErrType); + cntx->SendError(facade::UnknownSubCmd(sub_cmd, "SLOWLOG"), facade::kSyntaxErrType); return; } else if (argc == 2) { string_view length = facade::ArgS(args, 1); int64_t num; if ((!absl::SimpleAtoi(length, &num)) || (num < -1)) { - (*cntx)->SendError("count should be greater than or equal to -1"); + cntx->SendError("count should be greater than or equal to -1"); return; } if (num >= 0) { @@ -239,40 +239,41 @@ void SlowLogGet(dfly::CmdArgList args, dfly::ConnectionContext* cntx, dfly::Serv requested_slow_log_length = std::min(merged_slow_log.size(), requested_slow_log_length); - (*cntx)->StartArray(requested_slow_log_length); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(requested_slow_log_length); for (size_t i = 0; i < requested_slow_log_length; ++i) { const auto& entry = merged_slow_log[i].first; const auto& args = entry.cmd_args; - (*cntx)->StartArray(6); + rb->StartArray(6); - (*cntx)->SendLong(entry.entry_id * service.proactor_pool().size() + merged_slow_log[i].second); - (*cntx)->SendLong(entry.unix_timestamp / 1000000000); - (*cntx)->SendLong(entry.execution_time_micro); + rb->SendLong(entry.entry_id * service.proactor_pool().size() + merged_slow_log[i].second); + rb->SendLong(entry.unix_timestamp / 1000000000); + rb->SendLong(entry.execution_time_micro); // if we truncated the args, there is one pseudo-element containing the number of truncated // args that we must add, so the result length is increased by 1 size_t len = args.size() + int(args.size() < entry.original_length); - (*cntx)->StartArray(len); + rb->StartArray(len); for (const auto& arg : args) { if (arg.second > 0) { auto suffix = absl::StrCat("... (", arg.second, " more bytes)"); auto cmd_arg = arg.first.substr(0, dfly::kMaximumSlowlogArgLength - suffix.length()); - (*cntx)->SendBulkString(absl::StrCat(cmd_arg, suffix)); + rb->SendBulkString(absl::StrCat(cmd_arg, suffix)); } else { - (*cntx)->SendBulkString(arg.first); + rb->SendBulkString(arg.first); } } // if we truncated arguments - add a special string to indicate that. if (args.size() < entry.original_length) { - (*cntx)->SendBulkString( + rb->SendBulkString( absl::StrCat("... (", entry.original_length - args.size(), " more arguments)")); } - (*cntx)->SendBulkString(entry.client_ip); - (*cntx)->SendBulkString(entry.client_name); + rb->SendBulkString(entry.client_ip); + rb->SendBulkString(entry.client_name); } return; } @@ -1114,7 +1115,7 @@ void ServerFamily::DbSize(CmdArgList args, ConnectionContext* cntx) { }, [](ShardId) { return true; }); - return (*cntx)->SendLong(num_keys.load(memory_order_relaxed)); + return cntx->SendLong(num_keys.load(memory_order_relaxed)); } void ServerFamily::BreakOnShutdown() { @@ -1157,18 +1158,18 @@ void ServerFamily::FlushDb(CmdArgList args, ConnectionContext* cntx) { void ServerFamily::FlushAll(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 1) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } DCHECK(cntx->transaction); Drakarys(cntx->transaction, DbSlice::kDbAll); - (*cntx)->SendOk(); + cntx->SendOk(); } void ServerFamily::Auth(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 2) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } // non admin port auth @@ -1185,16 +1186,16 @@ void ServerFamily::Auth(CmdArgList args, ConnectionContext* cntx) { cntx->acl_categories = cred.acl_categories; cntx->acl_commands = cred.acl_commands; cntx->authenticated = true; - return (*cntx)->SendOk(); + return cntx->SendOk(); } auto& log = ServerState::tlocal()->acl_log; using Reason = acl::AclLog::Reason; log.Add(*cntx, "AUTH", Reason::AUTH, std::string(username)); - return (*cntx)->SendError(facade::kAuthRejected); + return cntx->SendError(facade::kAuthRejected); } if (!cntx->req_auth) { - return (*cntx)->SendError( + return cntx->SendError( "AUTH called without any password configured for " "admin port. Are you sure your configuration is correct?"); } @@ -1202,9 +1203,9 @@ void ServerFamily::Auth(CmdArgList args, ConnectionContext* cntx) { string_view pass = ArgS(args, 0); if (pass == GetPassword()) { cntx->authenticated = true; - (*cntx)->SendOk(); + cntx->SendOk(); } else { - (*cntx)->SendError(facade::kAuthRejected); + cntx->SendError(facade::kAuthRejected); } } @@ -1224,37 +1225,37 @@ void ServerFamily::Client(CmdArgList args, ConnectionContext* cntx) { } if (sub_cmd == "SETINFO") { - return (*cntx)->SendOk(); + return cntx->SendOk(); } LOG_FIRST_N(ERROR, 10) << "Subcommand " << sub_cmd << " not supported"; - return (*cntx)->SendError(UnknownSubCmd(sub_cmd, "CLIENT"), kSyntaxErrType); + return cntx->SendError(UnknownSubCmd(sub_cmd, "CLIENT"), kSyntaxErrType); } void ServerFamily::ClientSetName(CmdArgList args, ConnectionContext* cntx) { if (args.size() == 1) { cntx->conn()->SetName(string{ArgS(args, 0)}); - return (*cntx)->SendOk(); + return cntx->SendOk(); } else { - return (*cntx)->SendError(facade::kSyntaxErr); + return cntx->SendError(facade::kSyntaxErr); } } void ServerFamily::ClientGetName(CmdArgList args, ConnectionContext* cntx) { if (!args.empty()) { - return (*cntx)->SendError(facade::kSyntaxErr); + return cntx->SendError(facade::kSyntaxErr); } - auto name = cntx->conn()->GetName(); - if (!name.empty()) { - return (*cntx)->SendBulkString(name); + auto* rb = static_cast(cntx->reply_builder()); + if (auto name = cntx->conn()->GetName(); !name.empty()) { + return rb->SendBulkString(name); } else { - return (*cntx)->SendNull(); + return rb->SendNull(); } } void ServerFamily::ClientList(CmdArgList args, ConnectionContext* cntx) { if (!args.empty()) { - return (*cntx)->SendError(facade::kSyntaxErr); + return cntx->SendError(facade::kSyntaxErr); } vector client_info; @@ -1275,7 +1276,8 @@ void ServerFamily::ClientList(CmdArgList args, ConnectionContext* cntx) { string result = absl::StrJoin(client_info, "\n"); result.append("\n"); - return (*cntx)->SendBulkString(result); + auto* rb = static_cast(cntx->reply_builder()); + return rb->SendBulkString(result); } void ServerFamily::ClientPause(CmdArgList args, ConnectionContext* cntx) { @@ -1287,7 +1289,7 @@ void ServerFamily::ClientPause(CmdArgList args, ConnectionContext* cntx) { pause_state = parser.ToUpper().Switch("WRITE", ClientPause::WRITE, "ALL", ClientPause::ALL); } if (auto err = parser.Error(); err) { - return (*cntx)->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); } // Set global pause state and track commands that are running when the pause state is flipped. @@ -1309,7 +1311,7 @@ void ServerFamily::ClientPause(CmdArgList args, ConnectionContext* cntx) { service_.proactor_pool().Await([pause_state](util::ProactorBase* pb) { ServerState::tlocal()->SetPauseState(pause_state, false); }); - return (*cntx)->SendError("Failed to pause all running clients"); + return cntx->SendError("Failed to pause all running clients"); } // We should not expire/evict keys while clients are puased. @@ -1336,7 +1338,7 @@ void ServerFamily::ClientPause(CmdArgList args, ConnectionContext* cntx) { } }).Detach(); - (*cntx)->SendOk(); + cntx->SendOk(); } void ServerFamily::Config(CmdArgList args, ConnectionContext* cntx) { @@ -1345,7 +1347,7 @@ void ServerFamily::Config(CmdArgList args, ConnectionContext* cntx) { if (sub_cmd == "SET") { if (args.size() != 3) { - return (*cntx)->SendError(WrongNumArgsError("config|set")); + return cntx->SendError(WrongNumArgsError("config|set")); } ToLower(&args[1]); @@ -1356,19 +1358,19 @@ void ServerFamily::Config(CmdArgList args, ConnectionContext* cntx) { const char kErrPrefix[] = "CONFIG SET failed (possibly related to argument '"; switch (result) { case ConfigRegistry::SetResult::OK: - return (*cntx)->SendOk(); + return cntx->SendOk(); case ConfigRegistry::SetResult::UNKNOWN: - return (*cntx)->SendError( + return cntx->SendError( absl::StrCat("Unknown option or number of arguments for CONFIG SET - '", param, "'"), kConfigErrType); case ConfigRegistry::SetResult::READONLY: - return (*cntx)->SendError( - absl::StrCat(kErrPrefix, param, "') - can't set immutable config"), kConfigErrType); + return cntx->SendError(absl::StrCat(kErrPrefix, param, "') - can't set immutable config"), + kConfigErrType); case ConfigRegistry::SetResult::INVALID: - return (*cntx)->SendError(absl::StrCat(kErrPrefix, param, "') - argument can not be set"), - kConfigErrType); + return cntx->SendError(absl::StrCat(kErrPrefix, param, "') - argument can not be set"), + kConfigErrType); } ABSL_UNREACHABLE(); } @@ -1390,8 +1392,8 @@ void ServerFamily::Config(CmdArgList args, ConnectionContext* cntx) { res.push_back(flag->CurrentValue()); } } - - return (*cntx)->SendStringArr(res, RedisReplyBuilder::MAP); + auto* rb = static_cast(cntx->reply_builder()); + return rb->SendStringArr(res, RedisReplyBuilder::MAP); } if (sub_cmd == "RESETSTAT") { @@ -1404,9 +1406,9 @@ void ServerFamily::Config(CmdArgList args, ConnectionContext* cntx) { stats.pipelined_cmd_cnt = 0; }); - return (*cntx)->SendOk(); + return cntx->SendOk(); } else { - return (*cntx)->SendError(UnknownSubCmd(sub_cmd, "CONFIG"), kSyntaxErrType); + return cntx->SendError(UnknownSubCmd(sub_cmd, "CONFIG"), kSyntaxErrType); } } @@ -1433,7 +1435,7 @@ void ServerFamily::Save(CmdArgList args, ConnectionContext* cntx) { string err_detail; bool new_version = absl::GetFlag(FLAGS_df_snapshot_format); if (args.size() > 2) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } if (args.size() >= 1) { @@ -1444,7 +1446,7 @@ void ServerFamily::Save(CmdArgList args, ConnectionContext* cntx) { } else if (sub_cmd == "RDB") { new_version = false; } else { - return (*cntx)->SendError(UnknownSubCmd(sub_cmd, "SAVE"), kSyntaxErrType); + return cntx->SendError(UnknownSubCmd(sub_cmd, "SAVE"), kSyntaxErrType); } } @@ -1455,9 +1457,9 @@ void ServerFamily::Save(CmdArgList args, ConnectionContext* cntx) { GenericError ec = DoSave(new_version, basename, cntx->transaction); if (ec) { - (*cntx)->SendError(ec.Format()); + cntx->SendError(ec.Format()); } else { - (*cntx)->SendOk(); + cntx->SendOk(); } } @@ -1539,7 +1541,7 @@ Metrics ServerFamily::GetMetrics() const { void ServerFamily::Info(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 1) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } string_view section; @@ -1824,8 +1826,8 @@ void ServerFamily::Info(CmdArgList args, ConnectionContext* cntx) { if (should_enter("CLUSTER")) { append("cluster_enabled", ClusterConfig::IsEnabledOrEmulated()); } - - (*cntx)->SendBulkString(info); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendBulkString(info); } void ServerFamily::Hello(CmdArgList args, ConnectionContext* cntx) { @@ -1842,7 +1844,7 @@ void ServerFamily::Hello(CmdArgList args, ConnectionContext* cntx) { is_resp3 = proto_version == "3"; bool valid_proto_version = proto_version == "2" || is_resp3; if (!valid_proto_version) { - (*cntx)->SendError(UnknownCmd("HELLO", args)); + cntx->SendError(UnknownCmd("HELLO", args)); return; } @@ -1859,7 +1861,7 @@ void ServerFamily::Hello(CmdArgList args, ConnectionContext* cntx) { clientname = ArgS(args, i + 1); i += 1; } else { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } } @@ -1869,13 +1871,13 @@ void ServerFamily::Hello(CmdArgList args, ConnectionContext* cntx) { if (username == "default" && password == GetPassword()) { cntx->authenticated = true; } else { - (*cntx)->SendError(facade::kAuthRejected); + cntx->SendError(facade::kAuthRejected); return; } } if (cntx->req_auth && !cntx->authenticated) { - (*cntx)->SendError( + cntx->SendError( "-NOAUTH HELLO must be called with the client already " "authenticated, otherwise the HELLO AUTH " "option can be used to authenticate the client and " @@ -1887,30 +1889,31 @@ void ServerFamily::Hello(CmdArgList args, ConnectionContext* cntx) { cntx->conn()->SetName(string{clientname}); } + auto* rb = static_cast(cntx->reply_builder()); int proto_version = 2; if (is_resp3) { proto_version = 3; - (*cntx)->SetResp3(true); + rb->SetResp3(true); } else { // Issuing hello 2 again is valid and should switch back to RESP2 - (*cntx)->SetResp3(false); + rb->SetResp3(false); } - (*cntx)->StartCollection(7, RedisReplyBuilder::MAP); - (*cntx)->SendBulkString("server"); - (*cntx)->SendBulkString("redis"); - (*cntx)->SendBulkString("version"); - (*cntx)->SendBulkString(kRedisVersion); - (*cntx)->SendBulkString("dragonfly_version"); - (*cntx)->SendBulkString(GetVersion()); - (*cntx)->SendBulkString("proto"); - (*cntx)->SendLong(proto_version); - (*cntx)->SendBulkString("id"); - (*cntx)->SendLong(cntx->conn()->GetClientId()); - (*cntx)->SendBulkString("mode"); - (*cntx)->SendBulkString("standalone"); - (*cntx)->SendBulkString("role"); - (*cntx)->SendBulkString((*ServerState::tlocal()).is_master ? "master" : "slave"); + rb->StartCollection(7, RedisReplyBuilder::MAP); + rb->SendBulkString("server"); + rb->SendBulkString("redis"); + rb->SendBulkString("version"); + rb->SendBulkString(kRedisVersion); + rb->SendBulkString("dragonfly_version"); + rb->SendBulkString(GetVersion()); + rb->SendBulkString("proto"); + rb->SendLong(proto_version); + rb->SendBulkString("id"); + rb->SendLong(cntx->conn()->GetClientId()); + rb->SendBulkString("mode"); + rb->SendBulkString("standalone"); + rb->SendBulkString("role"); + rb->SendBulkString((*ServerState::tlocal()).is_master ? "master" : "slave"); } void ServerFamily::ReplicaOfInternal(string_view host, string_view port_sv, ConnectionContext* cntx, @@ -1933,12 +1936,12 @@ void ServerFamily::ReplicaOfInternal(string_view host, string_view port_sv, Conn GlobalState::ACTIVE) << "Server is set to replica no one, yet state is not active!"; - return (*cntx)->SendOk(); + return cntx->SendOk(); } uint32_t port; if (!absl::SimpleAtoi(port_sv, &port) || port < 1 || port > 65535) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } @@ -1946,7 +1949,7 @@ void ServerFamily::ReplicaOfInternal(string_view host, string_view port_sv, Conn if (auto new_state = service_.SwitchState(GlobalState::ACTIVE, GlobalState::LOADING); new_state.first != GlobalState::LOADING) { LOG(WARNING) << GlobalStateName(new_state.first) << " in progress, ignored"; - (*cntx)->SendError("Invalid state"); + cntx->SendError("Invalid state"); return; } @@ -2014,37 +2017,37 @@ void ServerFamily::ReplTakeOver(CmdArgList args, ConnectionContext* cntx) { auto timeout_sec = parser.Next(); if (timeout_sec < 0) { - return (*cntx)->SendError("timeout is negative"); + return cntx->SendError("timeout is negative"); } bool save_flag = static_cast(parser.Check("SAVE").IgnoreCase()); if (parser.HasNext()) - return (*cntx)->SendError(absl::StrCat("Unsupported option:", string_view(parser.Next()))); + return cntx->SendError(absl::StrCat("Unsupported option:", string_view(parser.Next()))); if (auto err = parser.Error(); err) - return (*cntx)->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); if (ServerState::tlocal()->is_master) - return (*cntx)->SendError("Already a master instance"); + return cntx->SendError("Already a master instance"); auto repl_ptr = replica_; CHECK(repl_ptr); auto info = replica_->GetInfo(); if (!info.full_sync_done) { - return (*cntx)->SendError("Full sync not done"); + return cntx->SendError("Full sync not done"); } std::error_code ec = replica_->TakeOver(ArgS(args, 0), save_flag); if (ec) - return (*cntx)->SendError("Couldn't execute takeover"); + return cntx->SendError("Couldn't execute takeover"); LOG(INFO) << "Takeover successful, promoting this instance to master."; service_.proactor_pool().AwaitFiberOnAll( [&](util::ProactorBase* pb) { ServerState::tlocal()->is_master = true; }); replica_->Stop(); replica_.reset(); - return (*cntx)->SendOk(); + return cntx->SendOk(); } void ServerFamily::ReplConf(CmdArgList args, ConnectionContext* cntx) { @@ -2070,17 +2073,18 @@ void ServerFamily::ReplConf(CmdArgList args, ConnectionContext* cntx) { cntx->replica_conn = true; // The response for 'capa dragonfly' is: - (*cntx)->StartArray(4); - (*cntx)->SendSimpleString(master_id_); - (*cntx)->SendSimpleString(sync_id); - (*cntx)->SendLong(replica_info->flows.size()); - (*cntx)->SendLong(unsigned(DflyVersion::CURRENT_VER)); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(4); + rb->SendSimpleString(master_id_); + rb->SendSimpleString(sync_id); + rb->SendLong(replica_info->flows.size()); + rb->SendLong(unsigned(DflyVersion::CURRENT_VER)); return; } } else if (cmd == "LISTENING-PORT") { uint32_t replica_listening_port; if (!absl::SimpleAtoi(arg, &replica_listening_port)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } cntx->conn_state.replication_info.repl_listening_port = replica_listening_port; @@ -2092,7 +2096,7 @@ void ServerFamily::ReplConf(CmdArgList args, ConnectionContext* cntx) { } else if (cmd == "CLIENT-VERSION" && args.size() == 2) { unsigned version; if (!absl::SimpleAtoi(arg, &version)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } dfly_cmd_->SetDflyClientVersion(cntx, DflyVersion(version)); } else if (cmd == "ACK" && args.size() == 2) { @@ -2118,43 +2122,44 @@ void ServerFamily::ReplConf(CmdArgList args, ConnectionContext* cntx) { } } - (*cntx)->SendOk(); + cntx->SendOk(); return; err: LOG(ERROR) << "Error in receiving command: " << args; - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); } void ServerFamily::Role(CmdArgList args, ConnectionContext* cntx) { + auto* rb = static_cast(cntx->reply_builder()); ServerState& etl = *ServerState::tlocal(); if (etl.is_master) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString("master"); + rb->StartArray(2); + rb->SendBulkString("master"); auto vec = dfly_cmd_->GetReplicasRoleInfo(); - (*cntx)->StartArray(vec.size()); + rb->StartArray(vec.size()); for (auto& data : vec) { - (*cntx)->StartArray(3); - (*cntx)->SendBulkString(data.address); - (*cntx)->SendBulkString(absl::StrCat(data.listening_port)); - (*cntx)->SendBulkString(data.state); + rb->StartArray(3); + rb->SendBulkString(data.address); + rb->SendBulkString(absl::StrCat(data.listening_port)); + rb->SendBulkString(data.state); } } else { unique_lock lk{replicaof_mu_}; Replica::Info rinfo = replica_->GetInfo(); - (*cntx)->StartArray(4); - (*cntx)->SendBulkString("replica"); - (*cntx)->SendBulkString(rinfo.host); - (*cntx)->SendBulkString(absl::StrCat(rinfo.port)); + rb->StartArray(4); + rb->SendBulkString("replica"); + rb->SendBulkString(rinfo.host); + rb->SendBulkString(absl::StrCat(rinfo.port)); if (rinfo.full_sync_done) { - (*cntx)->SendBulkString("stable_sync"); + rb->SendBulkString("stable_sync"); } else if (rinfo.full_sync_in_progress) { - (*cntx)->SendBulkString("full_sync"); + rb->SendBulkString("full_sync"); } else if (rinfo.master_link_established) { - (*cntx)->SendBulkString("preparation"); + rb->SendBulkString("preparation"); } else { - (*cntx)->SendBulkString("connecting"); + rb->SendBulkString("connecting"); } } } @@ -2179,24 +2184,25 @@ void ServerFamily::LastSave(CmdArgList args, ConnectionContext* cntx) { lock_guard lk(save_mu_); save_time = last_save_info_->save_time; } - (*cntx)->SendLong(save_time); + cntx->SendLong(save_time); } void ServerFamily::Latency(CmdArgList args, ConnectionContext* cntx) { + auto* rb = static_cast(cntx->reply_builder()); ToUpper(&args[0]); string_view sub_cmd = ArgS(args, 0); if (sub_cmd == "LATEST") { - return (*cntx)->SendEmptyArray(); + return rb->SendEmptyArray(); } LOG_FIRST_N(ERROR, 10) << "Subcommand " << sub_cmd << " not supported"; - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); } void ServerFamily::ShutdownCmd(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 1) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } @@ -2206,7 +2212,7 @@ void ServerFamily::ShutdownCmd(CmdArgList args, ConnectionContext* cntx) { } else if (absl::EqualsIgnoreCase(sub_cmd, "NOSAVE")) { save_on_shutdown_ = false; } else { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } } @@ -2215,7 +2221,7 @@ void ServerFamily::ShutdownCmd(CmdArgList args, ConnectionContext* cntx) { [](ProactorBase* pb) { ServerState::tlocal()->EnterLameDuck(); }); CHECK_NOTNULL(acceptor_)->Stop(); - (*cntx)->SendOk(); + cntx->SendOk(); } void ServerFamily::SyncGeneric(std::string_view repl_master_id, uint64_t offs, @@ -2223,7 +2229,7 @@ void ServerFamily::SyncGeneric(std::string_view repl_master_id, uint64_t offs, if (cntx->async_dispatch) { // SYNC is a special command that should not be sent in batch with other commands. // It should be the last command since afterwards the server just dumps the replication data. - (*cntx)->SendError("Can not sync in pipeline mode"); + cntx->SendError("Can not sync in pipeline mode"); return; } @@ -2255,7 +2261,8 @@ void ServerFamily::SlowLog(CmdArgList args, ConnectionContext* cntx) { "HELP", " Prints this help.", }; - (*cntx)->SendSimpleStrArr(help); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendSimpleStrArr(help); return; } @@ -2265,41 +2272,42 @@ void ServerFamily::SlowLog(CmdArgList args, ConnectionContext* cntx) { lengths[index] = ServerState::tlocal()->GetSlowLog().Length(); }); int sum = std::accumulate(lengths.begin(), lengths.end(), 0); - return (*cntx)->SendLong(sum); + return cntx->SendLong(sum); } if (sub_cmd == "RESET") { service_.proactor_pool().AwaitFiberOnAll( [](auto index, auto* context) { ServerState::tlocal()->GetSlowLog().Reset(); }); - return (*cntx)->SendOk(); + return cntx->SendOk(); } if (sub_cmd == "GET") { return SlowLogGet(args, cntx, service_, sub_cmd); } - (*cntx)->SendError(UnknownSubCmd(sub_cmd, "SLOWLOG"), kSyntaxErrType); + cntx->SendError(UnknownSubCmd(sub_cmd, "SLOWLOG"), kSyntaxErrType); } void ServerFamily::Module(CmdArgList args, ConnectionContext* cntx) { ToUpper(&args[0]); if (ArgS(args, 0) != "LIST") - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); - (*cntx)->StartArray(2); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(2); // Json - (*cntx)->StartCollection(2, RedisReplyBuilder::MAP); - (*cntx)->SendSimpleString("name"); - (*cntx)->SendSimpleString("ReJSON"); - (*cntx)->SendSimpleString("ver"); - (*cntx)->SendLong(20'000); + rb->StartCollection(2, RedisReplyBuilder::MAP); + rb->SendSimpleString("name"); + rb->SendSimpleString("ReJSON"); + rb->SendSimpleString("ver"); + rb->SendLong(20'000); // Search - (*cntx)->StartCollection(2, RedisReplyBuilder::MAP); - (*cntx)->SendSimpleString("name"); - (*cntx)->SendSimpleString("search"); - (*cntx)->SendSimpleString("ver"); - (*cntx)->SendLong(20'000); // we target v2 + rb->StartCollection(2, RedisReplyBuilder::MAP); + rb->SendSimpleString("name"); + rb->SendSimpleString("search"); + rb->SendSimpleString("ver"); + rb->SendLong(20'000); // we target v2 } #define HFUNC(x) SetHandler(HandlerFunc(this, &ServerFamily::x)) diff --git a/src/server/set_family.cc b/src/server/set_family.cc index 7066a9c00..f530b597a 100644 --- a/src/server/set_family.cc +++ b/src/server/set_family.cc @@ -1083,10 +1083,10 @@ void SAdd(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - return (*cntx)->SendLong(result.value()); + return cntx->SendLong(result.value()); } - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } void SIsMember(CmdArgList args, ConnectionContext* cntx) { @@ -1107,9 +1107,9 @@ void SIsMember(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHop(std::move(cb)); switch (result.status()) { case OpStatus::OK: - return (*cntx)->SendLong(1); + return cntx->SendLong(1); default: - return (*cntx)->SendLong(0); + return cntx->SendLong(0); } } @@ -1134,14 +1134,15 @@ void SMIsMember(CmdArgList args, ConnectionContext* cntx) { return find_res.status(); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHop(std::move(cb)); if (result == OpStatus::KEY_NOTFOUND) { memberships.assign(vals.size(), "0"); - return (*cntx)->SendStringArr(memberships); + return rb->SendStringArr(memberships); } else if (result == OpStatus::OK) { - return (*cntx)->SendStringArr(memberships); + return rb->SendStringArr(memberships); } - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } void SMove(CmdArgList args, ConnectionContext* cntx) { @@ -1156,11 +1157,11 @@ void SMove(CmdArgList args, ConnectionContext* cntx) { OpResult result = mover.Commit(cntx->transaction); if (!result) { - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); return; } - (*cntx)->SendLong(result.value()); + cntx->SendLong(result.value()); } void SRem(CmdArgList args, ConnectionContext* cntx) { @@ -1178,11 +1179,11 @@ void SRem(CmdArgList args, ConnectionContext* cntx) { switch (result.status()) { case OpStatus::WRONG_TYPE: - return (*cntx)->SendError(kWrongTypeErr); + return cntx->SendError(kWrongTypeErr); case OpStatus::OK: - return (*cntx)->SendLong(result.value()); + return cntx->SendLong(result.value()); default: - return (*cntx)->SendLong(0); + return cntx->SendLong(0); } } @@ -1202,11 +1203,11 @@ void SCard(CmdArgList args, ConnectionContext* cntx) { switch (result.status()) { case OpStatus::OK: - return (*cntx)->SendLong(result.value()); + return cntx->SendLong(result.value()); case OpStatus::WRONG_TYPE: - return (*cntx)->SendError(kWrongTypeErr); + return cntx->SendError(kWrongTypeErr); default: - return (*cntx)->SendLong(0); + return cntx->SendLong(0); } } @@ -1216,7 +1217,7 @@ void SPop(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 1) { string_view arg = ArgS(args, 1); if (!absl::SimpleAtoi(arg, &count)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } } @@ -1225,22 +1226,23 @@ void SPop(CmdArgList args, ConnectionContext* cntx) { return OpPop(t->GetOpArgs(shard), key, count); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result || result.status() == OpStatus::KEY_NOTFOUND) { if (args.size() == 1) { // SPOP key if (result.status() == OpStatus::KEY_NOTFOUND) { - (*cntx)->SendNull(); + rb->SendNull(); } else { DCHECK_EQ(1u, result.value().size()); - (*cntx)->SendBulkString(result.value().front()); + rb->SendBulkString(result.value().front()); } } else { // SPOP key cnt - (*cntx)->SendStringArr(*result, RedisReplyBuilder::SET); + rb->SendStringArr(*result, RedisReplyBuilder::SET); } return; } - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } void SDiff(CmdArgList args, ConnectionContext* cntx) { @@ -1263,7 +1265,7 @@ void SDiff(CmdArgList args, ConnectionContext* cntx) { cntx->transaction->ScheduleSingleHop(std::move(cb)); ResultSetView rsv = DiffResultVec(result_set, src_shard); if (!rsv) { - (*cntx)->SendError(rsv.status()); + cntx->SendError(rsv.status()); return; } @@ -1271,7 +1273,8 @@ void SDiff(CmdArgList args, ConnectionContext* cntx) { if (cntx->conn_state.script_info) { // sort under script sort(arr.begin(), arr.end()); } - (*cntx)->SendStringArr(arr, RedisReplyBuilder::SET); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendStringArr(arr, RedisReplyBuilder::SET); } void SDiffStore(CmdArgList args, ConnectionContext* cntx) { @@ -1311,7 +1314,7 @@ void SDiffStore(CmdArgList args, ConnectionContext* cntx) { ResultSetView rsv = DiffResultVec(result_set, src_shard); if (!rsv) { cntx->transaction->Conclude(); - (*cntx)->SendError(rsv.status()); + cntx->SendError(rsv.status()); return; } @@ -1325,7 +1328,7 @@ void SDiffStore(CmdArgList args, ConnectionContext* cntx) { }; cntx->transaction->Execute(std::move(store_cb), true); - (*cntx)->SendLong(result.size()); + cntx->SendLong(result.size()); } void SMembers(CmdArgList args, ConnectionContext* cntx) { @@ -1339,9 +1342,10 @@ void SMembers(CmdArgList args, ConnectionContext* cntx) { if (cntx->conn_state.script_info) { // sort under script sort(svec.begin(), svec.end()); } - (*cntx)->SendStringArr(*result, RedisReplyBuilder::SET); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendStringArr(*result, RedisReplyBuilder::SET); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1353,10 +1357,10 @@ void SRandMember(CmdArgList args, ConnectionContext* cntx) { int count = is_count ? parser.Next() : 1; if (parser.HasNext()) - return (*cntx)->SendError(WrongNumArgsError("SRANDMEMBER")); + return cntx->SendError(WrongNumArgsError("SRANDMEMBER")); if (auto err = parser.Error(); err) - return (*cntx)->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); const unsigned ucount = std::abs(count); @@ -1385,7 +1389,7 @@ void SRandMember(CmdArgList args, ConnectionContext* cntx) { }; OpResult result = cntx->transaction->ScheduleSingleHopT(cb); - + auto* rb = static_cast(cntx->reply_builder()); if (result) { if (count < 0 && !result->empty()) { for (auto i = result->size(); i < ucount; ++i) { @@ -1393,15 +1397,15 @@ void SRandMember(CmdArgList args, ConnectionContext* cntx) { result->push_back(result->front()); } } - (*cntx)->SendStringArr(*result, RedisReplyBuilder::SET); + rb->SendStringArr(*result, RedisReplyBuilder::SET); } else if (result.status() == OpStatus::KEY_NOTFOUND) { if (is_count) { - (*cntx)->SendStringArr(StringVec(), RedisReplyBuilder::SET); + rb->SendStringArr(StringVec(), RedisReplyBuilder::SET); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -1421,9 +1425,10 @@ void SInter(CmdArgList args, ConnectionContext* cntx) { if (cntx->conn_state.script_info) { // sort under script sort(arr.begin(), arr.end()); } - (*cntx)->SendStringArr(arr, RedisReplyBuilder::SET); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendStringArr(arr, RedisReplyBuilder::SET); } else { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1451,7 +1456,7 @@ void SInterStore(CmdArgList args, ConnectionContext* cntx) { OpResult result = InterResultVec(result_set, inter_shard_cnt.load(memory_order_relaxed)); if (!result) { cntx->transaction->Conclude(); - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); return; } @@ -1464,20 +1469,20 @@ void SInterStore(CmdArgList args, ConnectionContext* cntx) { }; cntx->transaction->Execute(std::move(store_cb), true); - (*cntx)->SendLong(result->size()); + cntx->SendLong(result->size()); } void SInterCard(CmdArgList args, ConnectionContext* cntx) { unsigned num_keys; if (!absl::SimpleAtoi(ArgS(args, 0), &num_keys)) - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); unsigned limit = 0; if (args.size() == (num_keys + 3) && ArgS(args, 1 + num_keys) == "LIMIT") { if (!absl::SimpleAtoi(ArgS(args, num_keys + 2), &limit)) - return (*cntx)->SendError("limit can't be negative"); + return cntx->SendError("limit can't be negative"); } else if (args.size() > (num_keys + 1)) - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); ResultStringVec result_set(shard_set->size(), OpStatus::SKIPPED); auto cb = [&](Transaction* t, EngineShard* shard) { @@ -1489,7 +1494,7 @@ void SInterCard(CmdArgList args, ConnectionContext* cntx) { OpResult result = InterResultVec(result_set, cntx->transaction->GetUniqueShardCnt(), limit); - return (*cntx)->SendLong(result->size()); + return cntx->SendLong(result->size()); } void SUnion(CmdArgList args, ConnectionContext* cntx) { @@ -1509,9 +1514,10 @@ void SUnion(CmdArgList args, ConnectionContext* cntx) { if (cntx->conn_state.script_info) { // sort under script sort(arr.begin(), arr.end()); } - (*cntx)->SendStringArr(arr, RedisReplyBuilder::SET); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendStringArr(arr, RedisReplyBuilder::SET); } else { - (*cntx)->SendError(unionset.status()); + cntx->SendError(unionset.status()); } } @@ -1538,7 +1544,7 @@ void SUnionStore(CmdArgList args, ConnectionContext* cntx) { ResultSetView unionset = UnionResultVec(result_set); if (!unionset) { cntx->transaction->Conclude(); - (*cntx)->SendError(unionset.status()); + cntx->SendError(unionset.status()); return; } @@ -1553,7 +1559,7 @@ void SUnionStore(CmdArgList args, ConnectionContext* cntx) { }; cntx->transaction->Execute(std::move(store_cb), true); - (*cntx)->SendLong(result.size()); + cntx->SendLong(result.size()); } void SScan(CmdArgList args, ConnectionContext* cntx) { @@ -1563,19 +1569,19 @@ void SScan(CmdArgList args, ConnectionContext* cntx) { uint64_t cursor = 0; if (!absl::SimpleAtoi(token, &cursor)) { - return (*cntx)->SendError("invalid cursor"); + return cntx->SendError("invalid cursor"); } // SSCAN key cursor [MATCH pattern] [COUNT count] if (args.size() > 6) { DVLOG(1) << "got " << args.size() << " this is more than it should be"; - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } OpResult ops = ScanOpts::TryFrom(args.subspan(2)); if (!ops) { DVLOG(1) << "SScan invalid args - return " << ops << " to the user"; - return (*cntx)->SendError(ops.status()); + return cntx->SendError(ops.status()); } ScanOpts scan_op = ops.value(); @@ -1584,16 +1590,17 @@ void SScan(CmdArgList args, ConnectionContext* cntx) { return OpScan(t->GetOpArgs(shard), key, &cursor, scan_op); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() != OpStatus::WRONG_TYPE) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(absl::StrCat(cursor)); - (*cntx)->StartArray(result->size()); // Within scan the return page is of type array + rb->StartArray(2); + rb->SendBulkString(absl::StrCat(cursor)); + rb->StartArray(result->size()); // Within scan the return page is of type array for (const auto& k : *result) { - (*cntx)->SendBulkString(k); + rb->SendBulkString(k); } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -1605,7 +1612,7 @@ void SAddEx(CmdArgList args, ConnectionContext* cntx) { constexpr uint32_t kMaxTtl = (1UL << 26); if (!absl::SimpleAtoi(ttl_str, &ttl_sec) || ttl_sec == 0 || ttl_sec > kMaxTtl) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } vector vals(args.size() - 2); @@ -1621,10 +1628,10 @@ void SAddEx(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - return (*cntx)->SendLong(result.value()); + return cntx->SendLong(result.value()); } - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } // namespace diff --git a/src/server/stream_family.cc b/src/server/stream_family.cc index 1d58779e8..a8435677e 100644 --- a/src/server/stream_family.cc +++ b/src/server/stream_family.cc @@ -1818,9 +1818,9 @@ void CreateGroup(CmdArgList args, string_view key, ConnectionContext* cntx) { OpStatus result = cntx->transaction->ScheduleSingleHop(std::move(cb)); switch (result) { case OpStatus::KEY_NOTFOUND: - return (*cntx)->SendError(kXGroupKeyNotFound); + return cntx->SendError(kXGroupKeyNotFound); default: - (*cntx)->SendError(result); + cntx->SendError(result); } } @@ -1832,13 +1832,13 @@ void DestroyGroup(string_view key, string_view gname, ConnectionContext* cntx) { OpStatus result = cntx->transaction->ScheduleSingleHop(std::move(cb)); switch (result) { case OpStatus::OK: - return (*cntx)->SendLong(1); + return cntx->SendLong(1); case OpStatus::SKIPPED: - return (*cntx)->SendLong(0); + return cntx->SendLong(0); case OpStatus::KEY_NOTFOUND: - return (*cntx)->SendError(kXGroupKeyNotFound); + return cntx->SendError(kXGroupKeyNotFound); default: - (*cntx)->SendError(result); + cntx->SendError(result); } } @@ -1851,15 +1851,15 @@ void CreateConsumer(string_view key, string_view gname, string_view consumer, switch (result.status()) { case OpStatus::OK: - return (*cntx)->SendLong(1); + return cntx->SendLong(1); case OpStatus::KEY_EXISTS: - return (*cntx)->SendLong(0); + return cntx->SendLong(0); case OpStatus::SKIPPED: - return (*cntx)->SendError(NoGroupError(key, gname)); + return cntx->SendError(NoGroupError(key, gname)); case OpStatus::KEY_NOTFOUND: - return (*cntx)->SendError(kXGroupKeyNotFound); + return cntx->SendError(kXGroupKeyNotFound); default: - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1873,13 +1873,13 @@ void DelConsumer(string_view key, string_view gname, string_view consumer, switch (result.status()) { case OpStatus::OK: - return (*cntx)->SendLong(*result); + return cntx->SendLong(*result); case OpStatus::SKIPPED: - return (*cntx)->SendError(NoGroupError(key, gname)); + return cntx->SendError(NoGroupError(key, gname)); case OpStatus::KEY_NOTFOUND: - return (*cntx)->SendError(kXGroupKeyNotFound); + return cntx->SendError(kXGroupKeyNotFound); default: - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } } @@ -1893,11 +1893,11 @@ void SetId(string_view key, string_view gname, CmdArgList args, ConnectionContex OpStatus result = cntx->transaction->ScheduleSingleHop(std::move(cb)); switch (result) { case OpStatus::SKIPPED: - return (*cntx)->SendError(NoGroupError(key, gname)); + return cntx->SendError(NoGroupError(key, gname)); case OpStatus::KEY_NOTFOUND: - return (*cntx)->SendError(kXGroupKeyNotFound); + return cntx->SendError(kXGroupKeyNotFound); default: - (*cntx)->SendError(result); + cntx->SendError(result); } } @@ -1916,7 +1916,8 @@ void XGroupHelp(CmdArgList args, ConnectionContext* cntx) { "SETID ", " Set the current group ID.", }; - return (*cntx)->SendSimpleStrArr(help_arr); + auto* rb = static_cast(cntx->reply_builder()); + return rb->SendSimpleStrArr(help_arr); } OpResult OpTrim(const OpArgs& op_args, const AddTrimOpts& opts) { @@ -1953,8 +1954,7 @@ optional> ParseAddOrTrimArgsOrReply(CmdArgList args, opts.no_mkstream = true; } else if ((arg == "MAXLEN" || arg == "MINID") && remaining_args >= 1) { if (opts.trim_strategy != TrimStrategy::kNone) { - (*cntx)->SendError("MAXLEN and MINID options at the same time are not compatible", - kSyntaxErr); + cntx->SendError("MAXLEN and MINID options at the same time are not compatible", kSyntaxErr); return std::nullopt; } @@ -1977,28 +1977,28 @@ optional> ParseAddOrTrimArgsOrReply(CmdArgList args, } if (opts.trim_strategy == TrimStrategy::kMaxLen && !absl::SimpleAtoi(arg, &opts.max_len)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return std::nullopt; } if (opts.trim_strategy == TrimStrategy::kMinId && !ParseID(arg, false, 0, &opts.minid)) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return std::nullopt; } } else if (arg == "LIMIT" && remaining_args >= 1 && opts.trim_strategy != TrimStrategy::kNone) { if (!opts.trim_approx) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return std::nullopt; } ++id_indx; if (!absl::SimpleAtoi(ArgS(args, id_indx), &opts.limit)) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return std::nullopt; } } else if (is_xadd) { // There are still remaining field args. break; } else { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return std::nullopt; } } @@ -2019,13 +2019,13 @@ void StreamFamily::XAdd(CmdArgList args, ConnectionContext* cntx) { args.remove_prefix(id_indx); if (args.size() < 2 || args.size() % 2 == 0) { - return (*cntx)->SendError(WrongNumArgsError("XADD"), kSyntaxErrType); + return cntx->SendError(WrongNumArgsError("XADD"), kSyntaxErrType); } string_view id = ArgS(args, 0); if (!ParseID(id, true, 0, &add_opts.parsed_id)) { - return (*cntx)->SendError(kInvalidStreamId, kSyntaxErrType); + return cntx->SendError(kInvalidStreamId, kSyntaxErrType); } args.remove_prefix(1); @@ -2035,16 +2035,17 @@ void StreamFamily::XAdd(CmdArgList args, ConnectionContext* cntx) { OpResult add_result = cntx->transaction->ScheduleSingleHopT(cb); if (add_result) { - return (*cntx)->SendBulkString(StreamIdRepr(*add_result)); + auto* rb = static_cast(cntx->reply_builder()); + return rb->SendBulkString(StreamIdRepr(*add_result)); } if (add_result.status() == OpStatus::STREAM_ID_SMALL) { - return (*cntx)->SendError( + return cntx->SendError( "The ID specified in XADD is equal or smaller than " "the target stream top item"); } - return (*cntx)->SendError(add_result.status()); + return cntx->SendError(add_result.status()); } absl::InlinedVector GetXclaimIds(CmdArgList& args) { @@ -2075,19 +2076,19 @@ void ParseXclaimOptions(CmdArgList& args, ClaimOpts& opts, ConnectionContext* cn if (arg == "IDLE") { arg = ArgS(args, ++i); if (!absl::SimpleAtoi(arg, &opts.delivery_time)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } continue; } else if (arg == "TIME") { arg = ArgS(args, ++i); if (!absl::SimpleAtoi(arg, &opts.delivery_time)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } continue; } else if (arg == "RETRYCOUNT") { arg = ArgS(args, ++i); if (!absl::SimpleAtoi(arg, &opts.retry)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } continue; } else if (arg == "LASTID") { @@ -2097,7 +2098,7 @@ void ParseXclaimOptions(CmdArgList& args, ClaimOpts& opts, ConnectionContext* cn if (ParseID(arg, true, 0, &parsed_id)) { opts.last_id = parsed_id.val; } else { - return (*cntx)->SendError(kInvalidStreamId, kSyntaxErrType); + return cntx->SendError(kInvalidStreamId, kSyntaxErrType); } continue; } @@ -2107,7 +2108,7 @@ void ParseXclaimOptions(CmdArgList& args, ClaimOpts& opts, ConnectionContext* cn } else if (arg == "JUSTID") { opts.flags |= kClaimJustID; } else { - return (*cntx)->SendError("Unknown argument given for XCLAIM command", kSyntaxErr); + return cntx->SendError("Unknown argument given for XCLAIM command", kSyntaxErr); } } } @@ -2118,7 +2119,7 @@ void StreamFamily::XClaim(CmdArgList args, ConnectionContext* cntx) { opts.group = ArgS(args, 1); opts.consumer = ArgS(args, 2); if (!absl::SimpleAtoi(ArgS(args, 3), &opts.min_idle_time)) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } // Ignore negative min-idle-time opts.min_idle_time = std::max(opts.min_idle_time, static_cast(0)); @@ -2127,7 +2128,7 @@ void StreamFamily::XClaim(CmdArgList args, ConnectionContext* cntx) { auto ids = GetXclaimIds(args); if (ids.empty()) { // No ids given. - return (*cntx)->SendError(kInvalidStreamId, kSyntaxErrType); + return cntx->SendError(kInvalidStreamId, kSyntaxErrType); } // parse the options @@ -2141,26 +2142,27 @@ void StreamFamily::XClaim(CmdArgList args, ConnectionContext* cntx) { }; OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (!result) { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); return; } + auto* rb = static_cast(cntx->reply_builder()); ClaimInfo cresult = result.value(); if (cresult.justid) { - (*cntx)->StartArray(cresult.ids.size()); + rb->StartArray(cresult.ids.size()); for (auto id : cresult.ids) { - (*cntx)->SendBulkString(StreamIdRepr(id)); + rb->SendBulkString(StreamIdRepr(id)); } } else { const RecordVec& crec = cresult.records; - (*cntx)->StartArray(crec.size()); + rb->StartArray(crec.size()); for (const auto& item : crec) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(StreamIdRepr(item.id)); - (*cntx)->StartArray(item.kv_arr.size() * 2); + rb->StartArray(2); + rb->SendBulkString(StreamIdRepr(item.id)); + rb->StartArray(item.kv_arr.size() * 2); for (const auto& [k, v] : item.kv_arr) { - (*cntx)->SendBulkString(k); - (*cntx)->SendBulkString(v); + rb->SendBulkString(k); + rb->SendBulkString(v); } } } @@ -2176,7 +2178,7 @@ void StreamFamily::XDel(CmdArgList args, ConnectionContext* cntx) { ParsedStreamId parsed_id; string_view str_id = ArgS(args, i); if (!ParseID(str_id, true, 0, &parsed_id)) { - return (*cntx)->SendError(kInvalidStreamId, kSyntaxErrType); + return cntx->SendError(kInvalidStreamId, kSyntaxErrType); } ids[i] = parsed_id.val; } @@ -2187,10 +2189,10 @@ void StreamFamily::XDel(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(cb); if (result || result.status() == OpStatus::KEY_NOTFOUND) { - return (*cntx)->SendLong(*result); + return cntx->SendLong(*result); } - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } void StreamFamily::XGroup(CmdArgList args, ConnectionContext* cntx) { @@ -2228,10 +2230,11 @@ void StreamFamily::XGroup(CmdArgList args, ConnectionContext* cntx) { } } - return (*cntx)->SendError(UnknownSubCmd(sub_cmd, "XGROUP")); + return cntx->SendError(UnknownSubCmd(sub_cmd, "XGROUP")); } void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) { + auto* rb = static_cast(cntx->reply_builder()); ToUpper(&args[0]); string_view sub_cmd = ArgS(args, 0); if (sub_cmd == "HELP") { @@ -2243,7 +2246,7 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) { " Show information about the stream.", "HELP", " Prints this help."}; - return (*cntx)->SendSimpleStrArr(help_arr); + return rb->SendSimpleStrArr(help_arr); } if (args.size() >= 2) { @@ -2260,41 +2263,41 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) { OpResult> result = shard_set->Await(sid, std::move(cb)); if (result) { - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); for (const auto& ginfo : *result) { string last_id = StreamIdRepr(ginfo.last_id); - (*cntx)->StartCollection(6, RedisReplyBuilder::MAP); - (*cntx)->SendBulkString("name"); - (*cntx)->SendBulkString(ginfo.name); - (*cntx)->SendBulkString("consumers"); - (*cntx)->SendLong(ginfo.consumer_size); - (*cntx)->SendBulkString("pending"); - (*cntx)->SendLong(ginfo.pending_size); - (*cntx)->SendBulkString("last-delivered-id"); - (*cntx)->SendBulkString(last_id); - (*cntx)->SendBulkString("entries-read"); + rb->StartCollection(6, RedisReplyBuilder::MAP); + rb->SendBulkString("name"); + rb->SendBulkString(ginfo.name); + rb->SendBulkString("consumers"); + rb->SendLong(ginfo.consumer_size); + rb->SendBulkString("pending"); + rb->SendLong(ginfo.pending_size); + rb->SendBulkString("last-delivered-id"); + rb->SendBulkString(last_id); + rb->SendBulkString("entries-read"); if (ginfo.entries_read != SCG_INVALID_ENTRIES_READ) { - (*cntx)->SendLong(ginfo.entries_read); + rb->SendLong(ginfo.entries_read); } else { - (*cntx)->SendNull(); + rb->SendNull(); } - (*cntx)->SendBulkString("lag"); + rb->SendBulkString("lag"); if (ginfo.lag != SCG_INVALID_LAG) { - (*cntx)->SendLong(ginfo.lag); + rb->SendLong(ginfo.lag); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } return; } - return (*cntx)->SendError(result.status()); + return rb->SendError(result.status()); } else if (sub_cmd == "STREAM") { int full = 0; size_t count = 10; // default count for xinfo streams if (args.size() == 4 || args.size() > 5) { - return (*cntx)->SendError( + return cntx->SendError( "unknown subcommand or wrong number of arguments for 'STREAM'. Try XINFO HELP."); } @@ -2303,7 +2306,7 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) { ToUpper(&args[2]); string_view full_arg = ArgS(args, 2); if (full_arg != "FULL") { - return (*cntx)->SendError( + return cntx->SendError( "unknown subcommand or wrong number of arguments for 'STREAM'. Try XINFO HELP."); } if (args.size() > 3) { @@ -2311,12 +2314,12 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) { string_view count_arg = ArgS(args, 3); string_view count_value_arg = ArgS(args, 4); if (count_arg != "COUNT") { - return (*cntx)->SendError( + return cntx->SendError( "unknown subcommand or wrong number of arguments for 'STREAM'. Try XINFO HELP."); } if (!absl::SimpleAtoi(count_value_arg, &count)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } } } @@ -2327,147 +2330,148 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) { return OpStreams(db_context, key, shard, full, count); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult sinfo = shard_set->Await(sid, std::move(cb)); if (sinfo) { if (full) { - (*cntx)->StartCollection(9, RedisReplyBuilder::MAP); + rb->StartCollection(9, RedisReplyBuilder::MAP); } else { - (*cntx)->StartCollection(10, RedisReplyBuilder::MAP); + rb->StartCollection(10, RedisReplyBuilder::MAP); } - (*cntx)->SendBulkString("length"); - (*cntx)->SendLong(sinfo->length); + rb->SendBulkString("length"); + rb->SendLong(sinfo->length); - (*cntx)->SendBulkString("radix-tree-keys"); - (*cntx)->SendLong(sinfo->radix_tree_keys); + rb->SendBulkString("radix-tree-keys"); + rb->SendLong(sinfo->radix_tree_keys); - (*cntx)->SendBulkString("radix-tree-nodes"); - (*cntx)->SendLong(sinfo->radix_tree_nodes); + rb->SendBulkString("radix-tree-nodes"); + rb->SendLong(sinfo->radix_tree_nodes); - (*cntx)->SendBulkString("last-generated-id"); - (*cntx)->SendBulkString(StreamIdRepr(sinfo->last_generated_id)); + rb->SendBulkString("last-generated-id"); + rb->SendBulkString(StreamIdRepr(sinfo->last_generated_id)); - (*cntx)->SendBulkString("max-deleted-entry-id"); - (*cntx)->SendBulkString(StreamIdRepr(sinfo->max_deleted_entry_id)); + rb->SendBulkString("max-deleted-entry-id"); + rb->SendBulkString(StreamIdRepr(sinfo->max_deleted_entry_id)); - (*cntx)->SendBulkString("entries-added"); - (*cntx)->SendLong(sinfo->entries_added); + rb->SendBulkString("entries-added"); + rb->SendLong(sinfo->entries_added); - (*cntx)->SendBulkString("recorded-first-entry-id"); - (*cntx)->SendBulkString(StreamIdRepr(sinfo->recorded_first_entry_id)); + rb->SendBulkString("recorded-first-entry-id"); + rb->SendBulkString(StreamIdRepr(sinfo->recorded_first_entry_id)); if (full) { - (*cntx)->SendBulkString("entries"); - (*cntx)->StartArray(sinfo->entries.size()); + rb->SendBulkString("entries"); + rb->StartArray(sinfo->entries.size()); for (const auto& entry : sinfo->entries) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(StreamIdRepr(entry.id)); - (*cntx)->StartArray(2); + rb->StartArray(2); + rb->SendBulkString(StreamIdRepr(entry.id)); + rb->StartArray(2); for (const auto& k_v : entry.kv_arr) { - (*cntx)->SendBulkString(k_v.first); - (*cntx)->SendBulkString(k_v.second); + rb->SendBulkString(k_v.first); + rb->SendBulkString(k_v.second); } } - (*cntx)->SendBulkString("groups"); - (*cntx)->StartArray(sinfo->cgroups.size()); + rb->SendBulkString("groups"); + rb->StartArray(sinfo->cgroups.size()); for (const auto& ginfo : sinfo->cgroups) { - (*cntx)->StartCollection(7, RedisReplyBuilder::MAP); + rb->StartCollection(7, RedisReplyBuilder::MAP); - (*cntx)->SendBulkString("name"); - (*cntx)->SendBulkString(ginfo.name); + rb->SendBulkString("name"); + rb->SendBulkString(ginfo.name); - (*cntx)->SendBulkString("last-delivered-id"); - (*cntx)->SendBulkString(StreamIdRepr(ginfo.last_id)); + rb->SendBulkString("last-delivered-id"); + rb->SendBulkString(StreamIdRepr(ginfo.last_id)); - (*cntx)->SendBulkString("entries-read"); + rb->SendBulkString("entries-read"); if (ginfo.entries_read != SCG_INVALID_ENTRIES_READ) { - (*cntx)->SendLong(ginfo.entries_read); + rb->SendLong(ginfo.entries_read); } else { - (*cntx)->SendNull(); + rb->SendNull(); } - (*cntx)->SendBulkString("lag"); + rb->SendBulkString("lag"); if (ginfo.lag != SCG_INVALID_LAG) { - (*cntx)->SendLong(ginfo.lag); + rb->SendLong(ginfo.lag); } else { - (*cntx)->SendNull(); + rb->SendNull(); } - (*cntx)->SendBulkString("pel-count"); - (*cntx)->SendLong(ginfo.pel_count); + rb->SendBulkString("pel-count"); + rb->SendLong(ginfo.pel_count); - (*cntx)->SendBulkString("pending"); - (*cntx)->StartArray(ginfo.stream_nack_vec.size()); + rb->SendBulkString("pending"); + rb->StartArray(ginfo.stream_nack_vec.size()); for (const auto& pending_info : ginfo.stream_nack_vec) { - (*cntx)->StartArray(4); - (*cntx)->SendBulkString(StreamIdRepr(pending_info.pel_id)); - (*cntx)->SendBulkString(pending_info.consumer_name); - (*cntx)->SendLong(pending_info.delivery_time); - (*cntx)->SendLong(pending_info.delivery_count); + rb->StartArray(4); + rb->SendBulkString(StreamIdRepr(pending_info.pel_id)); + rb->SendBulkString(pending_info.consumer_name); + rb->SendLong(pending_info.delivery_time); + rb->SendLong(pending_info.delivery_count); } - (*cntx)->SendBulkString("consumers"); - (*cntx)->StartArray(ginfo.consumer_info_vec.size()); + rb->SendBulkString("consumers"); + rb->StartArray(ginfo.consumer_info_vec.size()); for (const auto& consumer_info : ginfo.consumer_info_vec) { - (*cntx)->StartCollection(4, RedisReplyBuilder::MAP); + rb->StartCollection(4, RedisReplyBuilder::MAP); - (*cntx)->SendBulkString("name"); - (*cntx)->SendBulkString(consumer_info.name); + rb->SendBulkString("name"); + rb->SendBulkString(consumer_info.name); - (*cntx)->SendBulkString("seen-time"); - (*cntx)->SendLong(consumer_info.seen_time); + rb->SendBulkString("seen-time"); + rb->SendLong(consumer_info.seen_time); - (*cntx)->SendBulkString("pel-count"); - (*cntx)->SendLong(consumer_info.pel_count); + rb->SendBulkString("pel-count"); + rb->SendLong(consumer_info.pel_count); - (*cntx)->SendBulkString("pending"); + rb->SendBulkString("pending"); if (consumer_info.pending.size() == 0) { - (*cntx)->SendEmptyArray(); + rb->SendEmptyArray(); } else { - (*cntx)->StartArray(consumer_info.pending.size()); + rb->StartArray(consumer_info.pending.size()); } for (const auto& pending : consumer_info.pending) { - (*cntx)->StartArray(3); + rb->StartArray(3); - (*cntx)->SendBulkString(StreamIdRepr(pending.pel_id)); - (*cntx)->SendLong(pending.delivery_time); - (*cntx)->SendLong(pending.delivery_count); + rb->SendBulkString(StreamIdRepr(pending.pel_id)); + rb->SendLong(pending.delivery_time); + rb->SendLong(pending.delivery_count); } } } } else { - (*cntx)->SendBulkString("groups"); - (*cntx)->SendLong(sinfo->groups); + rb->SendBulkString("groups"); + rb->SendLong(sinfo->groups); - (*cntx)->SendBulkString("first-entry"); + rb->SendBulkString("first-entry"); if (sinfo->first_entry.kv_arr.size() != 0) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(StreamIdRepr(sinfo->first_entry.id)); - (*cntx)->StartArray(sinfo->first_entry.kv_arr.size() * 2); + rb->StartArray(2); + rb->SendBulkString(StreamIdRepr(sinfo->first_entry.id)); + rb->StartArray(sinfo->first_entry.kv_arr.size() * 2); for (pair k_v : sinfo->first_entry.kv_arr) { - (*cntx)->SendBulkString(k_v.first); - (*cntx)->SendBulkString(k_v.second); + rb->SendBulkString(k_v.first); + rb->SendBulkString(k_v.second); } } else { - (*cntx)->SendNullArray(); + rb->SendNullArray(); } - (*cntx)->SendBulkString("last-entry"); + rb->SendBulkString("last-entry"); if (sinfo->last_entry.kv_arr.size() != 0) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(StreamIdRepr(sinfo->last_entry.id)); - (*cntx)->StartArray(sinfo->last_entry.kv_arr.size() * 2); + rb->StartArray(2); + rb->SendBulkString(StreamIdRepr(sinfo->last_entry.id)); + rb->StartArray(sinfo->last_entry.kv_arr.size() * 2); for (pair k_v : sinfo->last_entry.kv_arr) { - (*cntx)->SendBulkString(k_v.first); - (*cntx)->SendBulkString(k_v.second); + rb->SendBulkString(k_v.first); + rb->SendBulkString(k_v.second); } } else { - (*cntx)->SendNullArray(); + rb->SendNullArray(); } } return; } - return (*cntx)->SendError(sinfo.status()); + return rb->SendError(sinfo.status()); } else if (sub_cmd == "CONSUMERS") { string_view stream_name = ArgS(args, 1); string_view group_name = ArgS(args, 2); @@ -2479,25 +2483,25 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) { OpResult> result = shard_set->Await(sid, std::move(cb)); if (result) { - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); for (const auto& consumer_info : *result) { - (*cntx)->StartCollection(3, RedisReplyBuilder::MAP); - (*cntx)->SendBulkString("name"); - (*cntx)->SendBulkString(consumer_info.name); - (*cntx)->SendBulkString("pending"); - (*cntx)->SendLong(consumer_info.pel_count); - (*cntx)->SendBulkString("idle"); - (*cntx)->SendLong(consumer_info.idle); + rb->StartCollection(3, RedisReplyBuilder::MAP); + rb->SendBulkString("name"); + rb->SendBulkString(consumer_info.name); + rb->SendBulkString("pending"); + rb->SendLong(consumer_info.pel_count); + rb->SendBulkString("idle"); + rb->SendLong(consumer_info.idle); } return; } if (result.status() == OpStatus::INVALID_VALUE) { - return (*cntx)->SendError(NoGroupError(stream_name, group_name)); + return rb->SendError(NoGroupError(stream_name, group_name)); } - return (*cntx)->SendError(result.status()); + return rb->SendError(result.status()); } } - return (*cntx)->SendError(UnknownSubCmd(sub_cmd, "XINFO")); + return rb->SendError(UnknownSubCmd(sub_cmd, "XINFO")); } void StreamFamily::XLen(CmdArgList args, ConnectionContext* cntx) { @@ -2506,10 +2510,10 @@ void StreamFamily::XLen(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(cb); if (result || result.status() == OpStatus::KEY_NOTFOUND) { - return (*cntx)->SendLong(*result); + return cntx->SendLong(*result); } - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); } bool ParseXpendingOptions(CmdArgList& args, PendingOpts& opts, ConnectionContext* cntx) { @@ -2520,7 +2524,7 @@ bool ParseXpendingOptions(CmdArgList& args, PendingOpts& opts, ConnectionContext if (arg == "IDLE" && args.size() > 4) { id_indx++; if (!absl::SimpleAtoi(ArgS(args, id_indx), &opts.min_idle_time)) { - (*cntx)->SendError(kInvalidIntErr, kSyntaxErrType); + cntx->SendError(kInvalidIntErr, kSyntaxErrType); return false; } // Ignore negative min_idle_time @@ -2529,7 +2533,7 @@ bool ParseXpendingOptions(CmdArgList& args, PendingOpts& opts, ConnectionContext id_indx = 0; } if (args.size() < 3) { - (*cntx)->SendError(WrongNumArgsError("XPENDING"), kSyntaxErrType); + cntx->SendError(WrongNumArgsError("XPENDING"), kSyntaxErrType); return false; } @@ -2539,17 +2543,17 @@ bool ParseXpendingOptions(CmdArgList& args, PendingOpts& opts, ConnectionContext id_indx++; string_view end = ArgS(args, id_indx); if (!ParseRangeId(start, &rs) || !ParseRangeId(end, &re)) { - (*cntx)->SendError(kInvalidStreamId, kSyntaxErrType); + cntx->SendError(kInvalidStreamId, kSyntaxErrType); return false; } if (rs.exclude && streamIncrID(&rs.parsed_id.val) != C_OK) { - (*cntx)->SendError("invalid start ID for the interval", kSyntaxErrType); + cntx->SendError("invalid start ID for the interval", kSyntaxErrType); return false; } if (re.exclude && streamDecrID(&re.parsed_id.val) != C_OK) { - (*cntx)->SendError("invalid end ID for the interval", kSyntaxErrType); + cntx->SendError("invalid end ID for the interval", kSyntaxErrType); return false; } id_indx++; @@ -2558,7 +2562,7 @@ bool ParseXpendingOptions(CmdArgList& args, PendingOpts& opts, ConnectionContext // Parse count if (!absl::SimpleAtoi(ArgS(args, id_indx), &opts.count)) { - (*cntx)->SendError(kInvalidIntErr, kSyntaxErrType); + cntx->SendError(kInvalidIntErr, kSyntaxErrType); return false; } @@ -2587,40 +2591,41 @@ void StreamFamily::XPending(CmdArgList args, ConnectionContext* cntx) { OpResult op_result = cntx->transaction->ScheduleSingleHopT(cb); if (!op_result) { if (op_result.status() == OpStatus::SKIPPED) - return (*cntx)->SendError(NoGroupError(key, opts.group_name)); - return (*cntx)->SendError(op_result.status()); + return cntx->SendError(NoGroupError(key, opts.group_name)); + return cntx->SendError(op_result.status()); } PendingResult result = op_result.value(); + auto* rb = static_cast(cntx->reply_builder()); if (std::holds_alternative(result)) { const auto& res = std::get(result); if (!res.count) { - return (*cntx)->SendEmptyArray(); + return rb->SendEmptyArray(); } - (*cntx)->StartArray(4); - (*cntx)->SendLong(res.count); - (*cntx)->SendBulkString(StreamIdRepr(res.start)); - (*cntx)->SendBulkString(StreamIdRepr(res.end)); - (*cntx)->StartArray(res.consumer_list.size()); + rb->StartArray(4); + rb->SendLong(res.count); + rb->SendBulkString(StreamIdRepr(res.start)); + rb->SendBulkString(StreamIdRepr(res.end)); + rb->StartArray(res.consumer_list.size()); for (auto& [consumer_name, count] : res.consumer_list) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(consumer_name); - (*cntx)->SendLong(count); + rb->StartArray(2); + rb->SendBulkString(consumer_name); + rb->SendLong(count); } } else { const auto& res = std::get(result); if (!res.size()) { - return (*cntx)->SendEmptyArray(); + return rb->SendEmptyArray(); } - (*cntx)->StartArray(res.size()); + rb->StartArray(res.size()); for (auto& item : res) { - (*cntx)->StartArray(4); - (*cntx)->SendBulkString(StreamIdRepr(item.start)); - (*cntx)->SendBulkString(item.consumer_name); - (*cntx)->SendLong(item.elapsed); - (*cntx)->SendLong(item.delivery_count); + rb->StartArray(4); + rb->SendBulkString(StreamIdRepr(item.start)); + rb->SendBulkString(item.consumer_name); + rb->SendLong(item.elapsed); + rb->SendLong(item.delivery_count); } } } @@ -2647,13 +2652,13 @@ std::optional ParseReadArgsOrReply(CmdArgList args, bool read_group, string_view arg = ArgS(args, id_indx); if (arg.size() - 1 < 2) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return std::nullopt; } if (arg != "GROUP") { const auto m = "Missing 'GROUP' in 'XREADGROUP' command"; - (*cntx)->SendError(m, kSyntaxErr); + cntx->SendError(m, kSyntaxErr); return std::nullopt; } id_indx++; @@ -2671,14 +2676,14 @@ std::optional ParseReadArgsOrReply(CmdArgList args, bool read_group, id_indx++; arg = ArgS(args, id_indx); if (!absl::SimpleAtoi(arg, &opts.timeout)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return std::nullopt; } } else if (arg == "COUNT" && remaining_args) { id_indx++; arg = ArgS(args, id_indx); if (!absl::SimpleAtoi(arg, &opts.count)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return std::nullopt; } } else if (opts.read_group && arg == "NOACK") { @@ -2689,20 +2694,20 @@ std::optional ParseReadArgsOrReply(CmdArgList args, bool read_group, size_t pair_count = args.size() - opts.streams_arg; if ((pair_count % 2) != 0) { const auto m = "Unbalanced list of streams: for each stream key an ID must be specified"; - (*cntx)->SendError(m, kSyntaxErr); + cntx->SendError(m, kSyntaxErr); return std::nullopt; } streams_count = pair_count / 2; break; } else { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return std::nullopt; } } // STREAMS option is required. if (opts.streams_arg == 0) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return std::nullopt; } @@ -2718,7 +2723,7 @@ std::optional ParseReadArgsOrReply(CmdArgList args, bool read_group, // Set ID to 0 so if the ID cannot be resolved (when the stream doesn't // exist) it takes the first entry added. if (opts.read_group) { - (*cntx)->SendError("The $ can be specified only when calling XREAD.", kSyntaxErr); + cntx->SendError("The $ can be specified only when calling XREAD.", kSyntaxErr); return std::nullopt; } id.val.ms = 0; @@ -2727,7 +2732,7 @@ std::optional ParseReadArgsOrReply(CmdArgList args, bool read_group, sitem.id = id; auto [_, is_inserted] = opts.stream_ids.emplace(key, sitem); if (!is_inserted) { - (*cntx)->SendError(kSameStreamFound); + cntx->SendError(kSameStreamFound); return std::nullopt; } continue; @@ -2735,7 +2740,7 @@ std::optional ParseReadArgsOrReply(CmdArgList args, bool read_group, if (idstr == ">") { if (!opts.read_group) { - (*cntx)->SendError( + cntx->SendError( "The > ID can be specified only when calling XREADGROUP using the GROUP " " option.", kSyntaxErr); @@ -2746,14 +2751,14 @@ std::optional ParseReadArgsOrReply(CmdArgList args, bool read_group, sitem.id = id; auto [_, is_inserted] = opts.stream_ids.emplace(key, sitem); if (!is_inserted) { - (*cntx)->SendError(kSameStreamFound); + cntx->SendError(kSameStreamFound); return std::nullopt; } continue; } if (!ParseID(idstr, true, 0, &id)) { - (*cntx)->SendError(kInvalidStreamId, kSyntaxErrType); + cntx->SendError(kInvalidStreamId, kSyntaxErrType); return std::nullopt; } @@ -2763,7 +2768,7 @@ std::optional ParseReadArgsOrReply(CmdArgList args, bool read_group, sitem.id = id; auto [_, is_inserted] = opts.stream_ids.emplace(key, sitem); if (!is_inserted) { - (*cntx)->SendError(kSameStreamFound); + cntx->SendError(kSameStreamFound); return std::nullopt; } } @@ -2797,10 +2802,11 @@ OpResult> StreamLastIDs(Transaction* trans) void XReadBlock(ReadOpts opts, ConnectionContext* cntx) { // If BLOCK is not set just return an empty array as there are no resolvable // entries. + auto* rb = static_cast(cntx->reply_builder()); if (opts.timeout == -1 || cntx->transaction->IsMulti()) { // Close the transaction and release locks. cntx->transaction->Conclude(); - return (*cntx)->SendNullArray(); + return rb->SendNullArray(); } auto wcb = [](Transaction* t, EngineShard* shard) { return t->GetShardArgs(shard->shard_id()); }; @@ -2810,7 +2816,7 @@ void XReadBlock(ReadOpts opts, ConnectionContext* cntx) { bool wait_succeeded = cntx->transaction->WaitOnWatch(tp, std::move(wcb)); if (!wait_succeeded) { - return (*cntx)->SendNullArray(); + return rb->SendNullArray(); } // Resolve the entry in the woken key. Note this must not use OpRead since @@ -2841,29 +2847,30 @@ void XReadBlock(ReadOpts opts, ConnectionContext* cntx) { if (result) { SinkReplyBuilder::ReplyAggregator agg(cntx->reply_builder()); - (*cntx)->StartArray(1); + rb->StartArray(1); - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(key); + rb->StartArray(2); + rb->SendBulkString(key); - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); for (const auto& item : *result) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(StreamIdRepr(item.id)); - (*cntx)->StartArray(item.kv_arr.size() * 2); + rb->StartArray(2); + rb->SendBulkString(StreamIdRepr(item.id)); + rb->StartArray(item.kv_arr.size() * 2); for (const auto& k_v : item.kv_arr) { - (*cntx)->SendBulkString(k_v.first); - (*cntx)->SendBulkString(k_v.second); + rb->SendBulkString(k_v.first); + rb->SendBulkString(k_v.second); } } return; } else { - return (*cntx)->SendNullArray(); + return rb->SendNullArray(); } } // Read entries from given streams void XReadImpl(CmdArgList args, std::optional opts, ConnectionContext* cntx) { + auto* rb = static_cast(cntx->reply_builder()); auto last_ids = StreamLastIDs(cntx->transaction); if (!last_ids) { // Close the transaction. @@ -2874,7 +2881,7 @@ void XReadImpl(CmdArgList args, std::optional opts, ConnectionContext* return; } - return (*cntx)->SendNullArray(); + return rb->SendNullArray(); } // Resolve '$' IDs and check if there are any streams with entries that can @@ -2890,7 +2897,7 @@ void XReadImpl(CmdArgList args, std::optional opts, ConnectionContext* // We are simply mimicking Redis' error message here. // However, we could actually report more precise error message. cntx->transaction->Conclude(); - cntx->SendError(NoGroupOrKey(stream, opts->group_name, " in XREADGROUP with GROUP option")); + rb->SendError(NoGroupOrKey(stream, opts->group_name, " in XREADGROUP with GROUP option")); return; } @@ -2925,7 +2932,7 @@ void XReadImpl(CmdArgList args, std::optional opts, ConnectionContext* string error_msg = NoGroupOrKey(stream, opts->group_name, " in XREADGROUP with GROUP option"); cntx->transaction->Conclude(); - cntx->SendError(error_msg); + rb->SendError(error_msg); return; } } @@ -2974,23 +2981,23 @@ void XReadImpl(CmdArgList args, std::optional opts, ConnectionContext* SinkReplyBuilder::ReplyAggregator agg(cntx->reply_builder()); - (*cntx)->StartArray(resolved_streams); + rb->StartArray(resolved_streams); for (size_t i = 0; i != res.size(); i++) { // Ignore empty streams. if (res[i].size() == 0) { continue; } - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(ArgS(args, i + opts->streams_arg)); - (*cntx)->StartArray(res[i].size()); + rb->StartArray(2); + rb->SendBulkString(ArgS(args, i + opts->streams_arg)); + rb->StartArray(res[i].size()); for (const auto& item : res[i]) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(StreamIdRepr(item.id)); - (*cntx)->StartArray(item.kv_arr.size() * 2); + rb->StartArray(2); + rb->SendBulkString(StreamIdRepr(item.id)); + rb->StartArray(item.kv_arr.size() * 2); for (const auto& k_v : item.kv_arr) { - (*cntx)->SendBulkString(k_v.first); - (*cntx)->SendBulkString(k_v.second); + rb->SendBulkString(k_v.first); + rb->SendBulkString(k_v.second); } } } @@ -3048,7 +3055,7 @@ void StreamFamily::XSetId(CmdArgList args, ConnectionContext* cntx) { ParsedStreamId parsed_id; if (!ParseID(idstr, true, 0, &parsed_id)) { - return (*cntx)->SendError(kInvalidStreamId, kSyntaxErrType); + return cntx->SendError(kInvalidStreamId, kSyntaxErrType); } auto cb = [&](Transaction* t, EngineShard* shard) { @@ -3058,14 +3065,14 @@ void StreamFamily::XSetId(CmdArgList args, ConnectionContext* cntx) { OpStatus result = cntx->transaction->ScheduleSingleHop(std::move(cb)); switch (result) { case OpStatus::STREAM_ID_SMALL: - return (*cntx)->SendError( + return cntx->SendError( "The ID specified in XSETID is smaller than the target stream top item"); case OpStatus::ENTRIES_ADDED_SMALL: - return (*cntx)->SendError( + return cntx->SendError( "The entries_added specified in XSETID is smaller than " "the target stream length"); default: - return (*cntx)->SendError(result); + return cntx->SendError(result); } } @@ -3083,9 +3090,9 @@ void StreamFamily::XTrim(CmdArgList args, ConnectionContext* cntx) { OpResult trim_result = cntx->transaction->ScheduleSingleHopT(cb); if (trim_result) { - return (*cntx)->SendLong(*trim_result); + return cntx->SendLong(*trim_result); } - return (*cntx)->SendError(trim_result.status()); + return cntx->SendError(trim_result.status()); } void StreamFamily::XRangeGeneric(CmdArgList args, bool is_rev, ConnectionContext* cntx) { @@ -3095,27 +3102,27 @@ void StreamFamily::XRangeGeneric(CmdArgList args, bool is_rev, ConnectionContext RangeOpts range_opts; RangeId rs, re; if (!ParseRangeId(start, &rs) || !ParseRangeId(end, &re)) { - return (*cntx)->SendError(kInvalidStreamId, kSyntaxErrType); + return cntx->SendError(kInvalidStreamId, kSyntaxErrType); } if (rs.exclude && streamIncrID(&rs.parsed_id.val) != C_OK) { - return (*cntx)->SendError("invalid start ID for the interval", kSyntaxErrType); + return cntx->SendError("invalid start ID for the interval", kSyntaxErrType); } if (re.exclude && streamDecrID(&re.parsed_id.val) != C_OK) { - return (*cntx)->SendError("invalid end ID for the interval", kSyntaxErrType); + return cntx->SendError("invalid end ID for the interval", kSyntaxErrType); } if (args.size() > 3) { if (args.size() != 5) { - return (*cntx)->SendError(WrongNumArgsError("XRANGE"), kSyntaxErrType); + return cntx->SendError(WrongNumArgsError("XRANGE"), kSyntaxErrType); } ToUpper(&args[3]); string_view opt = ArgS(args, 3); string_view val = ArgS(args, 4); if (opt != "COUNT" || !absl::SimpleAtoi(val, &range_opts.count)) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } @@ -3128,27 +3135,27 @@ void StreamFamily::XRangeGeneric(CmdArgList args, bool is_rev, ConnectionContext }; OpResult result = cntx->transaction->ScheduleSingleHopT(cb); - + auto* rb = static_cast(cntx->reply_builder()); if (result) { SinkReplyBuilder::ReplyAggregator agg(cntx->reply_builder()); - (*cntx)->StartArray(result->size()); + rb->StartArray(result->size()); for (const auto& item : *result) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(StreamIdRepr(item.id)); - (*cntx)->StartArray(item.kv_arr.size() * 2); + rb->StartArray(2); + rb->SendBulkString(StreamIdRepr(item.id)); + rb->StartArray(item.kv_arr.size() * 2); for (const auto& k_v : item.kv_arr) { - (*cntx)->SendBulkString(k_v.first); - (*cntx)->SendBulkString(k_v.second); + rb->SendBulkString(k_v.first); + rb->SendBulkString(k_v.second); } } return; } if (result.status() == OpStatus::KEY_NOTFOUND) { - return (*cntx)->SendEmptyArray(); + return rb->SendEmptyArray(); } - return (*cntx)->SendError(result.status()); + return rb->SendError(result.status()); } void StreamFamily::XAck(CmdArgList args, ConnectionContext* cntx) { @@ -3161,7 +3168,7 @@ void StreamFamily::XAck(CmdArgList args, ConnectionContext* cntx) { ParsedStreamId parsed_id; string_view str_id = ArgS(args, i); if (!ParseID(str_id, true, 0, &parsed_id)) { - return (*cntx)->SendError(kInvalidStreamId, kSyntaxErrType); + return cntx->SendError(kInvalidStreamId, kSyntaxErrType); } ids[i] = parsed_id.val; } @@ -3172,10 +3179,10 @@ void StreamFamily::XAck(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(cb); if (result || result.status() == OpStatus::KEY_NOTFOUND) { - return (*cntx)->SendLong(*result); + return cntx->SendLong(*result); } - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); return; } @@ -3185,7 +3192,7 @@ void StreamFamily::XAutoClaim(CmdArgList args, ConnectionContext* cntx) { opts.group = ArgS(args, 1); opts.consumer = ArgS(args, 2); if (!absl::SimpleAtoi(ArgS(args, 3), &opts.min_idle_time)) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } opts.min_idle_time = std::max((int64)0, opts.min_idle_time); @@ -3196,7 +3203,7 @@ void StreamFamily::XAutoClaim(CmdArgList args, ConnectionContext* cntx) { return; } if (rs.exclude && streamDecrID(&rs.parsed_id.val) != C_OK) { - return (*cntx)->SendError("invalid start ID for the interval", kSyntaxErrType); + return cntx->SendError("invalid start ID for the interval", kSyntaxErrType); } opts.start = rs.parsed_id.val; @@ -3209,10 +3216,10 @@ void StreamFamily::XAutoClaim(CmdArgList args, ConnectionContext* cntx) { if (arg == "COUNT") { arg = ArgS(args, ++i); if (!absl::SimpleAtoi(arg, &opts.count)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (opts.count <= 0) { - return (*cntx)->SendError("COUNT must be > 0"); + return cntx->SendError("COUNT must be > 0"); } continue; } @@ -3220,7 +3227,7 @@ void StreamFamily::XAutoClaim(CmdArgList args, ConnectionContext* cntx) { if (arg == "JUSTID") { opts.flags |= kClaimJustID; } else { - return (*cntx)->SendError("Unknown argument given for XAUTOCLAIM command", kSyntaxErr); + return cntx->SendError("Unknown argument given for XAUTOCLAIM command", kSyntaxErr); } } @@ -3230,40 +3237,40 @@ void StreamFamily::XAutoClaim(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::KEY_NOTFOUND) { - (*cntx)->SendError(NoGroupOrKey(key, opts.group)); + cntx->SendError(NoGroupOrKey(key, opts.group)); return; } if (!result) { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); return; } ClaimInfo cresult = result.value(); - - (*cntx)->StartArray(3); - (*cntx)->SendBulkString(StreamIdRepr(cresult.end_id)); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(3); + rb->SendBulkString(StreamIdRepr(cresult.end_id)); if (cresult.justid) { - (*cntx)->StartArray(cresult.ids.size()); + rb->StartArray(cresult.ids.size()); for (auto id : cresult.ids) { - (*cntx)->SendBulkString(StreamIdRepr(id)); + rb->SendBulkString(StreamIdRepr(id)); } } else { const RecordVec& crec = cresult.records; - (*cntx)->StartArray(crec.size()); + rb->StartArray(crec.size()); for (const auto& item : crec) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(StreamIdRepr(item.id)); - (*cntx)->StartArray(item.kv_arr.size() * 2); + rb->StartArray(2); + rb->SendBulkString(StreamIdRepr(item.id)); + rb->StartArray(item.kv_arr.size() * 2); for (const auto& [k, v] : item.kv_arr) { - (*cntx)->SendBulkString(k); - (*cntx)->SendBulkString(v); + rb->SendBulkString(k); + rb->SendBulkString(v); } } } - (*cntx)->StartArray(cresult.deleted_ids.size()); + rb->StartArray(cresult.deleted_ids.size()); for (auto id : cresult.deleted_ids) { - (*cntx)->SendBulkString(StreamIdRepr(id)); + rb->SendBulkString(StreamIdRepr(id)); } } diff --git a/src/server/string_family.cc b/src/server/string_family.cc index 4570e4ca1..9dc222ed4 100644 --- a/src/server/string_family.cc +++ b/src/server/string_family.cc @@ -791,11 +791,12 @@ void StringFamily::Set(CmdArgList args, ConnectionContext* cntx) { const auto result{SetGeneric(cntx, sparams, key, value, true)}; if (sparams.flags & SetCmd::SET_GET) { + auto* rb = static_cast(cntx->reply_builder()); // When SET_GET is used, the reply is not affected by whether anything was set. if (result->has_value()) { - (*cntx)->SendBulkString(result->value()); + rb->SendBulkString(result->value()); } else { - (*cntx)->SendNull(); + rb->SendNull(); } return; } @@ -853,17 +854,18 @@ void StringFamily::Get(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult result = trans->ScheduleSingleHopT(std::move(cb)); + auto* rb = static_cast(cntx->reply_builder()); if (result) { DVLOG(1) << "GET " << trans->DebugId() << ": " << key << " " << result.value(); - (*cntx)->SendBulkString(*result); + rb->SendBulkString(*result); } else { switch (result.status()) { case OpStatus::WRONG_TYPE: - (*cntx)->SendError(kWrongTypeErr); + rb->SendError(kWrongTypeErr); break; default: DVLOG(1) << "GET " << key << " nil"; - (*cntx)->SendNull(); + rb->SendNull(); } } } @@ -881,17 +883,18 @@ void StringFamily::GetDel(CmdArgList args, ConnectionContext* cntx) { Transaction* trans = cntx->transaction; OpResult result = trans->ScheduleSingleHopT(std::move(cb)); + auto* rb = static_cast(cntx->reply_builder()); if (result) { DVLOG(1) << "GET " << trans->DebugId() << ": " << key << " " << result.value(); - (*cntx)->SendBulkString(*result); + rb->SendBulkString(*result); } else { switch (result.status()) { case OpStatus::WRONG_TYPE: - (*cntx)->SendError(kWrongTypeErr); + rb->SendError(kWrongTypeErr); break; default: DVLOG(1) << "GET " << key << " nil"; - (*cntx)->SendNull(); + rb->SendNull(); } } } @@ -912,16 +915,17 @@ void StringFamily::GetSet(CmdArgList args, ConnectionContext* cntx) { OpStatus status = cntx->transaction->ScheduleSingleHop(std::move(cb)); if (status != OpStatus::OK) { - (*cntx)->SendError(status); + cntx->SendError(status); return; } + auto* rb = static_cast(cntx->reply_builder()); if (prev_val) { - (*cntx)->SendBulkString(*prev_val); + rb->SendBulkString(*prev_val); return; } - return (*cntx)->SendNull(); + return rb->SendNull(); } void StringFamily::GetEx(CmdArgList args, ConnectionContext* cntx) { @@ -938,16 +942,16 @@ void StringFamily::GetEx(CmdArgList args, ConnectionContext* cntx) { if (cur_arg == "EX" || cur_arg == "PX" || cur_arg == "EXAT" || cur_arg == "PXAT") { i++; if (i >= args.size()) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } string_view ex = ArgS(args, i); if (!absl::SimpleAtoi(ex, &int_arg)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (int_arg <= 0) { - return (*cntx)->SendError(InvalidExpireTime("getex")); + return cntx->SendError(InvalidExpireTime("getex")); } if (cur_arg == "EXAT" || cur_arg == "PXAT") { @@ -963,7 +967,7 @@ void StringFamily::GetEx(CmdArgList args, ConnectionContext* cntx) { } else if (cur_arg == "PERSIST") { exp_params.persist = true; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } @@ -989,16 +993,17 @@ void StringFamily::GetEx(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); + auto* rb = static_cast(cntx->reply_builder()); if (result) - return (*cntx)->SendBulkString(*result); + return rb->SendBulkString(*result); switch (result.status()) { case OpStatus::WRONG_TYPE: - (*cntx)->SendError(kWrongTypeErr); + rb->SendError(kWrongTypeErr); break; default: DVLOG(1) << "GET " << key << " nil"; - (*cntx)->SendNull(); + rb->SendNull(); } } @@ -1013,7 +1018,7 @@ void StringFamily::IncrBy(CmdArgList args, ConnectionContext* cntx) { int64_t val; if (!absl::SimpleAtoi(sval, &val)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } return IncrByGeneric(key, val, cntx); } @@ -1024,7 +1029,7 @@ void StringFamily::IncrByFloat(CmdArgList args, ConnectionContext* cntx) { double val; if (!absl::SimpleAtod(sval, &val)) { - return (*cntx)->SendError(kInvalidFloatErr); + return cntx->SendError(kInvalidFloatErr); } auto cb = [&](Transaction* t, EngineShard* shard) { @@ -1036,7 +1041,7 @@ void StringFamily::IncrByFloat(CmdArgList args, ConnectionContext* cntx) { DVLOG(2) << "IncrByGeneric " << key << "/" << result.value(); if (!result) { - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); } builder->SendDouble(result.value()); @@ -1053,10 +1058,10 @@ void StringFamily::DecrBy(CmdArgList args, ConnectionContext* cntx) { int64_t val; if (!absl::SimpleAtoi(sval, &val)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (val == INT64_MIN) { - return (*cntx)->SendError(kIncrOverflow); + return cntx->SendError(kIncrOverflow); } return IncrByGeneric(key, -val, cntx); @@ -1114,9 +1119,9 @@ void StringFamily::ExtendGeneric(CmdArgList args, bool prepend, ConnectionContex OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (!result) - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); else - return (*cntx)->SendLong(result.value()); + return cntx->SendLong(result.value()); } DCHECK(cntx->protocol() == Protocol::MEMCACHE); @@ -1142,11 +1147,11 @@ void StringFamily::SetExGeneric(bool seconds, CmdArgList args, ConnectionContext int32_t unit_vals; if (!absl::SimpleAtoi(ex, &unit_vals)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (unit_vals < 1 || unit_vals >= kMaxExpireDeadlineSec) { - return (*cntx)->SendError(InvalidExpireTime(cntx->cid->name())); + return cntx->SendError(InvalidExpireTime(cntx->cid->name())); } SetCmd::SetParams sparams; @@ -1163,7 +1168,7 @@ void StringFamily::SetExGeneric(bool seconds, CmdArgList args, ConnectionContext OpResult result = cntx->transaction->ScheduleSingleHop(std::move(cb)); - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); } void StringFamily::MGet(CmdArgList args, ConnectionContext* cntx) { @@ -1241,9 +1246,9 @@ void StringFamily::MSet(CmdArgList args, ConnectionContext* cntx) { OpStatus status = transaction->ScheduleSingleHop(std::move(cb)); if (status == OpStatus::OK) { - (*cntx)->SendOk(); + cntx->SendOk(); } else { - (*cntx)->SendError(status); + cntx->SendError(status); } } @@ -1280,7 +1285,7 @@ void StringFamily::MSetNx(CmdArgList args, ConnectionContext* cntx) { transaction->Execute(std::move(epilog_cb), true); - (*cntx)->SendLong(to_skip ? 0 : 1); + cntx->SendLong(to_skip ? 0 : 1); } void StringFamily::StrLen(CmdArgList args, ConnectionContext* cntx) { @@ -1298,9 +1303,9 @@ void StringFamily::StrLen(CmdArgList args, ConnectionContext* cntx) { OpResult result = trans->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } else { - (*cntx)->SendLong(result.value()); + cntx->SendLong(result.value()); } } @@ -1311,7 +1316,7 @@ void StringFamily::GetRange(CmdArgList args, ConnectionContext* cntx) { int32_t start, end; if (!absl::SimpleAtoi(from, &start) || !absl::SimpleAtoi(to, &end)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } auto cb = [&](Transaction* t, EngineShard* shard) { @@ -1322,9 +1327,10 @@ void StringFamily::GetRange(CmdArgList args, ConnectionContext* cntx) { OpResult result = trans->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } else { - (*cntx)->SendBulkString(result.value()); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendBulkString(result.value()); } } @@ -1335,16 +1341,16 @@ void StringFamily::SetRange(CmdArgList args, ConnectionContext* cntx) { int32_t start; if (!absl::SimpleAtoi(offset, &start)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } if (start < 0) { - return (*cntx)->SendError("offset is out of range"); + return cntx->SendError("offset is out of range"); } size_t min_size = start + value.size(); if (min_size > kMaxStrLen) { - return (*cntx)->SendError("string exceeds maximum allowed size"); + return cntx->SendError("string exceeds maximum allowed size"); } auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult { @@ -1355,9 +1361,9 @@ void StringFamily::SetRange(CmdArgList args, ConnectionContext* cntx) { OpResult result = trans->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); } else { - (*cntx)->SendLong(result.value()); + cntx->SendLong(result.value()); } } @@ -1381,21 +1387,21 @@ void StringFamily::ClThrottle(CmdArgList args, ConnectionContext* cntx) { uint64_t max_burst; const string_view max_burst_str = ArgS(args, 1); if (!absl::SimpleAtoi(max_burst_str, &max_burst)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } // Emit count of tokens per period uint64_t count; const string_view count_str = ArgS(args, 2); if (!absl::SimpleAtoi(count_str, &count)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } // Period of emitting count of tokens uint64_t period; const string_view period_str = ArgS(args, 3); if (!absl::SimpleAtoi(period_str, &period)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } // Apply quantity of tokens now @@ -1404,22 +1410,22 @@ void StringFamily::ClThrottle(CmdArgList args, ConnectionContext* cntx) { const string_view quantity_str = ArgS(args, 4); if (!absl::SimpleAtoi(quantity_str, &quantity)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } } if (max_burst > INT64_MAX - 1) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } const int64_t limit = max_burst + 1; if (period > UINT64_MAX / 1000 || count == 0 || period * 1000 / count > INT64_MAX) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } const int64_t emission_interval_ms = period * 1000 / count; if (emission_interval_ms == 0) { - return (*cntx)->SendError("zero rates are not supported"); + return cntx->SendError("zero rates are not supported"); } auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult> { @@ -1430,7 +1436,8 @@ void StringFamily::ClThrottle(CmdArgList args, ConnectionContext* cntx) { OpResult> result = trans->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->StartArray(result->size()); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(result->size()); auto& array = result.value(); int64_t retry_after_s = array[3] / 1000; @@ -1446,22 +1453,22 @@ void StringFamily::ClThrottle(CmdArgList args, ConnectionContext* cntx) { array[4] = reset_after_s; for (const auto& v : array) { - (*cntx)->SendLong(v); + rb->SendLong(v); } } else { switch (result.status()) { case OpStatus::WRONG_TYPE: - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); break; case OpStatus::INVALID_INT: case OpStatus::INVALID_VALUE: - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); break; case OpStatus::OUT_OF_MEMORY: - (*cntx)->SendError(kOutOfMemory); + cntx->SendError(kOutOfMemory); break; default: - (*cntx)->SendError(result.status()); + cntx->SendError(result.status()); break; } } diff --git a/src/server/zset_family.cc b/src/server/zset_family.cc old mode 100755 new mode 100644 index 183755423..04938e71e --- a/src/server/zset_family.cc +++ b/src/server/zset_family.cc @@ -173,12 +173,13 @@ struct ZParams { void OutputScoredArrayResult(const OpResult& result, const ZSetFamily::RangeParams& params, ConnectionContext* cntx) { if (result.status() == OpStatus::WRONG_TYPE) { - return (*cntx)->SendError(kWrongTypeErr); + return cntx->SendError(kWrongTypeErr); } LOG_IF(WARNING, !result && result.status() != OpStatus::KEY_NOTFOUND) << "Unexpected status " << result.status(); - (*cntx)->SendScoredArray(result.value(), params.with_scores); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendScoredArray(result.value(), params.with_scores); } OpResult FindZEntry(const ZParams& zparams, const OpArgs& op_args, string_view key, @@ -714,7 +715,7 @@ bool ParseLexBound(string_view src, ZSetFamily::LexBound* bound) { void SendAtLeastOneKeyError(ConnectionContext* cntx) { string name{cntx->cid->name()}; absl::AsciiStrToLower(&name); - (*cntx)->SendError(absl::StrCat("at least 1 input key is needed for ", name)); + cntx->SendError(absl::StrCat("at least 1 input key is needed for ", name)); } enum class AggType : uint8_t { SUM, MIN, MAX, NOOP }; @@ -1065,9 +1066,9 @@ struct SetOpArgs { void HandleOpStatus(ConnectionContext* cntx, OpStatus op_status) { switch (op_status) { case OpStatus::INVALID_FLOAT: - return (*cntx)->SendError("weight value is not a float", kSyntaxErrType); + return cntx->SendError("weight value is not a float", kSyntaxErrType); default: - return (*cntx)->SendError(op_status); + return cntx->SendError(op_status); } } @@ -1225,7 +1226,7 @@ void ZUnionFamilyInternal(CmdArgList args, bool store, ConnectionContext* cntx) ScoredMap result; for (auto& op_res : maps) { if (!op_res) - return (*cntx)->SendError(op_res.status()); + return cntx->SendError(op_res.status()); UnionScoredMap(&result, &op_res.value(), op_args.agg_type); } @@ -1246,14 +1247,15 @@ void ZUnionFamilyInternal(CmdArgList args, bool store, ConnectionContext* cntx) return OpStatus::OK; }; cntx->transaction->Execute(std::move(store_cb), true); - (*cntx)->SendLong(smvec.size()); + cntx->SendLong(smvec.size()); } else { std::sort(std::begin(smvec), std::end(smvec)); - (*cntx)->StartArray(smvec.size() * (op_args.with_scores ? 2 : 1)); + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(smvec.size() * (op_args.with_scores ? 2 : 1)); for (const auto& elem : smvec) { - (*cntx)->SendBulkString(elem.second); + rb->SendBulkString(elem.second); if (op_args.with_scores) { - (*cntx)->SendDouble(elem.first); + rb->SendDouble(elem.first); } } } @@ -1312,10 +1314,10 @@ void BZPopMinMax(CmdArgList args, ConnectionContext* cntx, bool is_max) { float timeout; auto timeout_str = ArgS(args, args.size() - 1); if (!absl::SimpleAtof(timeout_str, &timeout)) { - return (*cntx)->SendError("timeout is not a float or out of range"); + return cntx->SendError("timeout is not a float or out of range"); } if (timeout < 0) { - return (*cntx)->SendError("timeout is negative"); + return cntx->SendError("timeout is negative"); } VLOG(1) << "BZPop timeout(" << timeout << ")"; @@ -1330,26 +1332,26 @@ void BZPopMinMax(CmdArgList args, ConnectionContext* cntx, bool is_max) { unsigned(timeout * 1000)); cntx->conn_state.is_blocking = false; + auto* rb = static_cast(cntx->reply_builder()); if (popped_key) { DVLOG(1) << "BZPop " << transaction->DebugId() << " popped from key " << popped_key; // key. CHECK(popped_array->size() == 1); - (*cntx)->StartArray(3); - (*cntx)->SendBulkString(*popped_key); - (*cntx)->SendBulkString(popped_array->front().first); - return (*cntx)->SendDouble(popped_array->front().second); + rb->StartArray(3); + rb->SendBulkString(*popped_key); + rb->SendBulkString(popped_array->front().first); + return rb->SendDouble(popped_array->front().second); } DVLOG(1) << "result for " << transaction->DebugId() << " is " << popped_key.status(); - switch (popped_key.status()) { case OpStatus::WRONG_TYPE: - return (*cntx)->SendError(kWrongTypeErr); + return rb->SendError(kWrongTypeErr); case OpStatus::TIMED_OUT: - return (*cntx)->SendNullArray(); + return rb->SendNullArray(); default: LOG(ERROR) << "Unexpected error " << popped_key.status(); } - return (*cntx)->SendNullArray(); + return rb->SendNullArray(); } vector OpFetch(EngineShard* shard, Transaction* t) { @@ -1713,24 +1715,25 @@ void ZAddGeneric(string_view key, const ZParams& zparams, ScoredMemberSpan memb_ OpResult add_result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (base::_in(add_result.status(), {OpStatus::WRONG_TYPE, OpStatus::OUT_OF_MEMORY})) { - return (*cntx)->SendError(add_result.status()); + return cntx->SendError(add_result.status()); } + auto* rb = static_cast(cntx->reply_builder()); // KEY_NOTFOUND may happen in case of XX flag. if (add_result.status() == OpStatus::KEY_NOTFOUND) { if (zparams.flags & ZADD_IN_INCR) - (*cntx)->SendNull(); + rb->SendNull(); else - (*cntx)->SendLong(0); + rb->SendLong(0); } else if (add_result.status() == OpStatus::SKIPPED) { - (*cntx)->SendNull(); + rb->SendNull(); } else if (add_result->is_nan) { - (*cntx)->SendError(kScoreNaN); + rb->SendError(kScoreNaN); } else { if (zparams.flags & ZADD_IN_INCR) { - (*cntx)->SendDouble(add_result->new_score); + rb->SendDouble(add_result->new_score); } else { - (*cntx)->SendLong(add_result->num_updated); + rb->SendLong(add_result->num_updated); } } } @@ -1787,25 +1790,25 @@ void ZSetFamily::ZAdd(CmdArgList args, ConnectionContext* cntx) { } if ((args.size() - i) % 2 != 0) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } if ((zparams.flags & ZADD_IN_INCR) && (i + 2 < args.size())) { - (*cntx)->SendError("INCR option supports a single increment-element pair"); + cntx->SendError("INCR option supports a single increment-element pair"); return; } unsigned insert_mask = zparams.flags & (ZADD_IN_NX | ZADD_IN_XX); if (insert_mask == (ZADD_IN_NX | ZADD_IN_XX)) { - (*cntx)->SendError(kNxXxErr); + cntx->SendError(kNxXxErr); return; } constexpr auto kRangeOpt = ZADD_IN_GT | ZADD_IN_LT; if (((zparams.flags & ZADD_IN_NX) && (zparams.flags & kRangeOpt)) || ((zparams.flags & kRangeOpt) == kRangeOpt)) { - (*cntx)->SendError("GT, LT, and/or NX options at the same time are not compatible"); + cntx->SendError("GT, LT, and/or NX options at the same time are not compatible"); return; } @@ -1831,7 +1834,7 @@ void ZSetFamily::ZAdd(CmdArgList args, ConnectionContext* cntx) { // Parse the score. Treats Nan as invalid double. if (!ParseDouble(cur_arg, &val)) { VLOG(1) << "Bad score:" << cur_arg << "|"; - return (*cntx)->SendError(kInvalidFloatErr); + return cntx->SendError(kInvalidFloatErr); } string_view member = ArgS(args, i + 1); @@ -1872,11 +1875,11 @@ void ZSetFamily::ZCard(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); return; } - (*cntx)->SendLong(result.value()); + cntx->SendLong(result.value()); } void ZSetFamily::ZCount(CmdArgList args, ConnectionContext* cntx) { @@ -1887,7 +1890,7 @@ void ZSetFamily::ZCount(CmdArgList args, ConnectionContext* cntx) { ScoreInterval si; if (!ParseBound(min_s, &si.first) || !ParseBound(max_s, &si.second)) { - return (*cntx)->SendError(kFloatRangeErr); + return cntx->SendError(kFloatRangeErr); } auto cb = [&](Transaction* t, EngineShard* shard) { @@ -1896,9 +1899,9 @@ void ZSetFamily::ZCount(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); } else { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } } @@ -1913,10 +1916,11 @@ void ZSetFamily::ZDiff(CmdArgList args, ConnectionContext* cntx) { const string_view key = ArgS(args, 1); const ShardId sid = Shard(key, maps.size()); + auto* rb = static_cast(cntx->reply_builder()); // Extract the ScoredMap of the first key auto& sm = maps[sid]; if (sm.empty()) { - (*cntx)->SendEmptyArray(); + rb->SendEmptyArray(); return; } auto result = std::move(sm[0]); @@ -1950,11 +1954,11 @@ void ZSetFamily::ZDiff(CmdArgList args, ConnectionContext* cntx) { std::sort(std::begin(smvec), std::end(smvec)); const bool with_scores = ArgS(args, args.size() - 1) == "WITHSCORES"; - (*cntx)->StartArray(result.size() * (with_scores ? 2 : 1)); + rb->StartArray(result.size() * (with_scores ? 2 : 1)); for (const auto& [score, key] : smvec) { - (*cntx)->SendBulkString(key); + rb->SendBulkString(key); if (with_scores) { - (*cntx)->SendDouble(score); + rb->SendDouble(score); } } } @@ -1968,11 +1972,11 @@ void ZSetFamily::ZIncrBy(CmdArgList args, ConnectionContext* cntx) { if (!absl::SimpleAtod(score_arg, &scored_member.first)) { VLOG(1) << "Bad score:" << score_arg << "|"; - return (*cntx)->SendError(kInvalidFloatErr); + return cntx->SendError(kInvalidFloatErr); } if (isnan(scored_member.first)) { - return (*cntx)->SendError(kScoreNaN); + return cntx->SendError(kScoreNaN); } ZParams zparams; @@ -1984,18 +1988,19 @@ void ZSetFamily::ZIncrBy(CmdArgList args, ConnectionContext* cntx) { OpResult add_result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (add_result.status() == OpStatus::WRONG_TYPE) { - return (*cntx)->SendError(kWrongTypeErr); + return cntx->SendError(kWrongTypeErr); } + auto* rb = static_cast(cntx->reply_builder()); if (add_result.status() == OpStatus::SKIPPED) { - return (*cntx)->SendNull(); + return rb->SendNull(); } if (add_result->is_nan) { - return (*cntx)->SendError(kScoreNaN); + return rb->SendError(kScoreNaN); } - (*cntx)->SendDouble(add_result->new_score); + rb->SendDouble(add_result->new_score); } void ZSetFamily::ZInterStore(CmdArgList args, ConnectionContext* cntx) { @@ -2022,7 +2027,7 @@ void ZSetFamily::ZInterStore(CmdArgList args, ConnectionContext* cntx) { OpResult result = IntersectResults(maps, op_args.agg_type); if (!result) - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); ShardId dest_shard = Shard(dest_key, maps.size()); AddResult add_result; @@ -2042,7 +2047,7 @@ void ZSetFamily::ZInterStore(CmdArgList args, ConnectionContext* cntx) { cntx->transaction->Execute(std::move(store_cb), true); - (*cntx)->SendLong(smvec.size()); + cntx->SendLong(smvec.size()); } void ZSetFamily::ZInter(CmdArgList args, ConnectionContext* cntx) { @@ -2067,7 +2072,7 @@ void ZSetFamily::ZInter(CmdArgList args, ConnectionContext* cntx) { OpResult result = IntersectResults(maps, op_args.agg_type); if (!result) - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); std::vector> scored_array; scored_array.reserve(result.value().size()); @@ -2080,22 +2085,23 @@ void ZSetFamily::ZInter(CmdArgList args, ConnectionContext* cntx) { return a.second < b.second; }); - (*cntx)->SendScoredArray(scored_array, op_args_res->with_scores); + auto* rb = static_cast(cntx->reply_builder()); + rb->SendScoredArray(scored_array, op_args_res->with_scores); } void ZSetFamily::ZInterCard(CmdArgList args, ConnectionContext* cntx) { unsigned num_keys; if (!absl::SimpleAtoi(ArgS(args, 0), &num_keys)) { - return (*cntx)->SendError(OpStatus::SYNTAX_ERR); + return cntx->SendError(OpStatus::SYNTAX_ERR); } uint64_t limit = 0; if (args.size() == (1 + num_keys + 2) && ArgS(args, 1 + num_keys) == "LIMIT") { if (!absl::SimpleAtoi(ArgS(args, 1 + num_keys + 1), &limit)) { - return (*cntx)->SendError("limit value is not a positive integer", kSyntaxErrType); + return cntx->SendError("limit value is not a positive integer", kSyntaxErrType); } } else if (args.size() != 1 + num_keys) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } vector> maps(shard_set->size(), OpStatus::SKIPPED); @@ -2109,12 +2115,12 @@ void ZSetFamily::ZInterCard(CmdArgList args, ConnectionContext* cntx) { OpResult result = IntersectResults(maps, AggType::NOOP); if (!result) - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); if (0 < limit && limit < result.value().size()) { - return (*cntx)->SendLong(limit); + return cntx->SendLong(limit); } - (*cntx)->SendLong(result.value().size()); + cntx->SendLong(result.value().size()); } void ZSetFamily::ZPopMax(CmdArgList args, ConnectionContext* cntx) { @@ -2133,7 +2139,7 @@ void ZSetFamily::ZLexCount(CmdArgList args, ConnectionContext* cntx) { LexInterval li; if (!ParseLexBound(min_s, &li.first) || !ParseLexBound(max_s, &li.second)) { - return (*cntx)->SendError(kLexRangeErr); + return cntx->SendError(kLexRangeErr); } auto cb = [&](Transaction* t, EngineShard* shard) { @@ -2142,9 +2148,9 @@ void ZSetFamily::ZLexCount(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); } else { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } } @@ -2157,12 +2163,12 @@ void ZSetFamily::ZRange(CmdArgList args, ConnectionContext* cntx) { string_view cur_arg = ArgS(args, i); if (cur_arg == "BYSCORE") { if (range_params.interval_type == RangeParams::IntervalType::LEX) { - return (*cntx)->SendError("BYSCORE and BYLEX options are not compatible"); + return cntx->SendError("BYSCORE and BYLEX options are not compatible"); } range_params.interval_type = RangeParams::IntervalType::SCORE; } else if (cur_arg == "BYLEX") { if (range_params.interval_type == RangeParams::IntervalType::SCORE) { - return (*cntx)->SendError("BYSCORE and BYLEX options are not compatible"); + return cntx->SendError("BYSCORE and BYLEX options are not compatible"); } range_params.interval_type = RangeParams::IntervalType::LEX; } else if (cur_arg == "REV") { @@ -2171,10 +2177,10 @@ void ZSetFamily::ZRange(CmdArgList args, ConnectionContext* cntx) { range_params.with_scores = true; } else if (cur_arg == "LIMIT") { if (i + 3 > args.size()) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } if (!ParseLimit(ArgS(args, i + 1), ArgS(args, i + 2), &range_params)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } i += 2; } else { @@ -2231,14 +2237,14 @@ void ZSetFamily::ZRangeByLexInternal(CmdArgList args, bool reverse, ConnectionCo if (args.size() > 3) { if (args.size() != 6) - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); ToUpper(&args[3]); if (ArgS(args, 3) != "LIMIT") - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); if (!ParseLimit(ArgS(args, 4), ArgS(args, 5), &range_params)) - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } range_params.offset = offset; range_params.limit = count; @@ -2257,7 +2263,7 @@ void ZSetFamily::ZRemRangeByRank(CmdArgList args, ConnectionContext* cntx) { IndexInterval ii; if (!SimpleAtoi(min_s, &ii.first) || !SimpleAtoi(max_s, &ii.second)) { - return (*cntx)->SendError(kInvalidIntErr); + return cntx->SendError(kInvalidIntErr); } ZRangeSpec range_spec; @@ -2272,7 +2278,7 @@ void ZSetFamily::ZRemRangeByScore(CmdArgList args, ConnectionContext* cntx) { ScoreInterval si; if (!ParseBound(min_s, &si.first) || !ParseBound(max_s, &si.second)) { - return (*cntx)->SendError(kFloatRangeErr); + return cntx->SendError(kFloatRangeErr); } ZRangeSpec range_spec; @@ -2289,7 +2295,7 @@ void ZSetFamily::ZRemRangeByLex(CmdArgList args, ConnectionContext* cntx) { LexInterval li; if (!ParseLexBound(min_s, &li.first) || !ParseLexBound(max_s, &li.second)) { - return (*cntx)->SendError(kLexRangeErr); + return cntx->SendError(kLexRangeErr); } ZRangeSpec range_spec; @@ -2313,15 +2319,15 @@ void ZSetFamily::ZRem(CmdArgList args, ConnectionContext* cntx) { OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); } else { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } } void ZSetFamily::ZRandMember(CmdArgList args, ConnectionContext* cntx) { if (args.size() > 3) - return (*cntx)->SendError(WrongNumArgsError("ZRANDMEMBER")); + return cntx->SendError(WrongNumArgsError("ZRANDMEMBER")); ZRangeSpec range_spec; range_spec.interval = IndexInterval(0, -1); @@ -2335,10 +2341,10 @@ void ZSetFamily::ZRandMember(CmdArgList args, ConnectionContext* cntx) { range_spec.params.with_scores = static_cast(parser.Check("WITHSCORES").IgnoreCase()); if (parser.HasNext()) - return (*cntx)->SendError(absl::StrCat("Unsupported option:", string_view(parser.Next()))); + return cntx->SendError(absl::StrCat("Unsupported option:", string_view(parser.Next()))); if (auto err = parser.Error(); err) - return (*cntx)->SendError(err->MakeReply()); + return cntx->SendError(err->MakeReply()); bool sign = count < 0; range_spec.params.limit = std::abs(count); @@ -2348,7 +2354,7 @@ void ZSetFamily::ZRandMember(CmdArgList args, ConnectionContext* cntx) { }; OpResult result = cntx->transaction->ScheduleSingleHopT(cb); - + auto* rb = static_cast(cntx->reply_builder()); if (result) { if (sign && !result->empty()) { for (auto i = result->size(); i < range_spec.params.limit; ++i) { @@ -2356,15 +2362,15 @@ void ZSetFamily::ZRandMember(CmdArgList args, ConnectionContext* cntx) { result->push_back(result->front()); } } - (*cntx)->SendScoredArray(result.value(), range_spec.params.with_scores); + rb->SendScoredArray(result.value(), range_spec.params.with_scores); } else if (result.status() == OpStatus::KEY_NOTFOUND) { if (is_count) { - (*cntx)->SendScoredArray(ScoredArray(), range_spec.params.with_scores); + rb->SendScoredArray(ScoredArray(), range_spec.params.with_scores); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -2376,13 +2382,14 @@ void ZSetFamily::ZScore(CmdArgList args, ConnectionContext* cntx) { return OpScore(t->GetOpArgs(shard), key, member); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(kWrongTypeErr); + rb->SendError(kWrongTypeErr); } else if (!result) { - (*cntx)->SendNull(); + rb->SendNull(); } else { - (*cntx)->SendDouble(*result); + rb->SendDouble(*result); } } @@ -2390,16 +2397,16 @@ void ZSetFamily::ZMScore(CmdArgList args, ConnectionContext* cntx) { OpResult result = ZGetMembers(args, cntx); if (result.status() == OpStatus::WRONG_TYPE) { - return (*cntx)->SendError(kWrongTypeErr); + return cntx->SendError(kWrongTypeErr); } - - (*cntx)->StartArray(result->size()); // Array return type. + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(result->size()); // Array return type. const MScoreResponse& array = result.value(); for (const auto& p : array) { if (p) { - (*cntx)->SendDouble(*p); + rb->SendDouble(*p); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } } @@ -2411,13 +2418,13 @@ void ZSetFamily::ZScan(CmdArgList args, ConnectionContext* cntx) { uint64_t cursor = 0; if (!absl::SimpleAtoi(token, &cursor)) { - return (*cntx)->SendError("invalid cursor"); + return cntx->SendError("invalid cursor"); } OpResult ops = ScanOpts::TryFrom(args.subspan(2)); if (!ops) { DVLOG(1) << "Scan invalid args - return " << ops << " to the user"; - return (*cntx)->SendError(ops.status()); + return cntx->SendError(ops.status()); } ScanOpts scan_op = ops.value(); @@ -2425,16 +2432,17 @@ void ZSetFamily::ZScan(CmdArgList args, ConnectionContext* cntx) { return OpScan(t->GetOpArgs(shard), key, &cursor, scan_op); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() != OpStatus::WRONG_TYPE) { - (*cntx)->StartArray(2); - (*cntx)->SendBulkString(absl::StrCat(cursor)); - (*cntx)->StartArray(result->size()); // Within scan the returned page is of type array. + rb->StartArray(2); + rb->SendBulkString(absl::StrCat(cursor)); + rb->StartArray(result->size()); // Within scan the returned page is of type array. for (const auto& k : *result) { - (*cntx)->SendBulkString(k); + rb->SendBulkString(k); } } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -2451,7 +2459,7 @@ void ZSetFamily::ZRangeByScoreInternal(CmdArgList args, bool reverse, Connection range_params.interval_type = RangeParams::IntervalType::SCORE; range_params.reverse = reverse; if (!ParseRangeByScoreParams(args.subspan(3), &range_params)) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } ZRangeGeneric(args, range_params, cntx); } @@ -2464,9 +2472,9 @@ void ZSetFamily::ZRemRangeGeneric(string_view key, const ZRangeSpec& range_spec, OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); } else { - (*cntx)->SendLong(*result); + cntx->SendLong(*result); } } @@ -2482,7 +2490,7 @@ void ZSetFamily::ZRangeGeneric(CmdArgList args, RangeParams range_params, Connec case RangeParams::IntervalType::SCORE: { ScoreInterval si; if (!ParseBound(min_s, &si.first) || !ParseBound(max_s, &si.second)) { - return (*cntx)->SendError(kFloatRangeErr); + return cntx->SendError(kFloatRangeErr); } range_spec.interval = si; break; @@ -2490,7 +2498,7 @@ void ZSetFamily::ZRangeGeneric(CmdArgList args, RangeParams range_params, Connec case RangeParams::IntervalType::LEX: { LexInterval li; if (!ParseLexBound(min_s, &li.first) || !ParseLexBound(max_s, &li.second)) { - return (*cntx)->SendError(kLexRangeErr); + return cntx->SendError(kLexRangeErr); } range_spec.interval = li; break; @@ -2498,7 +2506,7 @@ void ZSetFamily::ZRangeGeneric(CmdArgList args, RangeParams range_params, Connec case RangeParams::IntervalType::RANK: { IndexInterval ii; if (!SimpleAtoi(min_s, &ii.first) || !SimpleAtoi(max_s, &ii.second)) { - (*cntx)->SendError(kInvalidIntErr); + cntx->SendError(kInvalidIntErr); return; } range_spec.interval = ii; @@ -2522,13 +2530,14 @@ void ZSetFamily::ZRankGeneric(CmdArgList args, bool reverse, ConnectionContext* return OpRank(t->GetOpArgs(shard), key, member, reverse); }; + auto* rb = static_cast(cntx->reply_builder()); OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result) { - (*cntx)->SendLong(*result); + rb->SendLong(*result); } else if (result.status() == OpStatus::KEY_NOTFOUND) { - (*cntx)->SendNull(); + rb->SendNull(); } else { - (*cntx)->SendError(result.status()); + rb->SendError(result.status()); } } @@ -2567,7 +2576,7 @@ void ZSetFamily::ZPopMinMax(CmdArgList args, bool reverse, ConnectionContext* cn if (args.size() > 1) { string_view count = ArgS(args, 1); if (!SimpleAtoi(count, &sc)) { - return (*cntx)->SendError(kUintErr); + return cntx->SendError(kUintErr); } } @@ -2619,12 +2628,12 @@ void ZSetFamily::GeoAdd(CmdArgList args, ConnectionContext* cntx) { args.remove_prefix(i); if (args.empty() || args.size() % 3 != 0) { - (*cntx)->SendError(kSyntaxErr); + cntx->SendError(kSyntaxErr); return; } if ((zparams.flags & ZADD_IN_NX) && (zparams.flags & ZADD_IN_XX)) { - (*cntx)->SendError(kNxXxErr); + cntx->SendError(kNxXxErr); return; } @@ -2640,7 +2649,7 @@ void ZSetFamily::GeoAdd(CmdArgList args, ConnectionContext* cntx) { string err = absl::StrCat("-ERR invalid longitude,latitude pair ", longitude, ",", latitude, ",", member); - return (*cntx)->SendError(err, kSyntaxErrType); + return cntx->SendError(err, kSyntaxErrType); } /* Turn the coordinates into the score of the element. */ @@ -2660,18 +2669,19 @@ void ZSetFamily::GeoHash(CmdArgList args, ConnectionContext* cntx) { OpResult result = ZGetMembers(args, cntx); if (result.status() == OpStatus::WRONG_TYPE) { - return (*cntx)->SendError(kWrongTypeErr); + return cntx->SendError(kWrongTypeErr); } - (*cntx)->StartArray(result->size()); // Array return type. + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(result->size()); // Array return type. const MScoreResponse& arr = result.value(); array buf; for (const auto& p : arr) { if (ToAsciiGeoHash(p, &buf)) { - (*cntx)->SendBulkString(string_view{buf.data(), buf.size() - 1}); + rb->SendBulkString(string_view{buf.data(), buf.size() - 1}); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } } @@ -2680,20 +2690,21 @@ void ZSetFamily::GeoPos(CmdArgList args, ConnectionContext* cntx) { OpResult result = ZGetMembers(args, cntx); if (result.status() != OpStatus::OK) { - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); } - (*cntx)->StartArray(result->size()); // Array return type. + auto* rb = static_cast(cntx->reply_builder()); + rb->StartArray(result->size()); // Array return type. const MScoreResponse& arr = result.value(); double xy[2]; for (const auto& p : arr) { if (ScoreToLongLat(p, xy)) { - (*cntx)->StartArray(2); - (*cntx)->SendDouble(xy[0]); - (*cntx)->SendDouble(xy[1]); + rb->StartArray(2); + rb->SendDouble(xy[0]); + rb->SendDouble(xy[1]); } else { - (*cntx)->SendNull(); + rb->SendNull(); } } } @@ -2706,33 +2717,34 @@ void ZSetFamily::GeoDist(CmdArgList args, ConnectionContext* cntx) { distance_multiplier = ExtractUnit(unit); args.remove_suffix(1); if (distance_multiplier < 0) { - return (*cntx)->SendError("unsupported unit provided. please use M, KM, FT, MI"); + return cntx->SendError("unsupported unit provided. please use M, KM, FT, MI"); } } else if (args.size() != 3) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } OpResult result = ZGetMembers(args, cntx); if (result.status() != OpStatus::OK) { - return (*cntx)->SendError(result.status()); + return cntx->SendError(result.status()); } const MScoreResponse& arr = result.value(); if (arr.size() != 2) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } + auto* rb = static_cast(cntx->reply_builder()); double xyxy[4]; // 2 pairs of score holding 2 locations for (size_t i = 0; i < arr.size(); i++) { if (!ScoreToLongLat(arr[i], xyxy + (i * 2))) { - return (*cntx)->SendNull(); + return rb->SendNull(); } } - return (*cntx)->SendDouble(geohashGetDistance(xyxy[0], xyxy[1], xyxy[2], xyxy[3]) / - distance_multiplier); + return rb->SendDouble(geohashGetDistance(xyxy[0], xyxy[1], xyxy[2], xyxy[3]) / + distance_multiplier); } namespace { @@ -2791,10 +2803,10 @@ bool MembersOfAllNeighbors(ConnectionContext* cntx, string_view key, const GeoHa OpResult> result_arrays = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result_arrays.status() == OpStatus::WRONG_TYPE) { - (*cntx)->SendError(kWrongTypeErr); + cntx->SendError(kWrongTypeErr); return false; } else if (result_arrays.status() == OpStatus::KEY_NOTFOUND) { - (*cntx)->SendError("Member not found"); + cntx->SendError("Member not found"); return false; } @@ -2845,9 +2857,10 @@ void GeoSearchGeneric(ConnectionContext* cntx, const GeoShape& shape_ref, string return; } + auto* rb = static_cast(cntx->reply_builder()); // if no matching results, the user gets an empty reply. if (ga.empty()) { - (*cntx)->SendNull(); + rb->SendNull(); return; } @@ -2865,21 +2878,21 @@ void GeoSearchGeneric(ConnectionContext* cntx, const GeoShape& shape_ref, string if (geo_ops.withcoord) { record_size++; } - (*cntx)->StartArray(ga.size()); + rb->StartArray(ga.size()); for (const auto& p : ga) { // [member, dist, x, y, hash] - (*cntx)->StartArray(record_size); - (*cntx)->SendBulkString(p.member); + rb->StartArray(record_size); + rb->SendBulkString(p.member); if (geo_ops.withdist) { - (*cntx)->SendDouble(p.dist / geo_ops.conversion); + rb->SendDouble(p.dist / geo_ops.conversion); } if (geo_ops.withhash) { - (*cntx)->SendDouble(p.score); + rb->SendDouble(p.score); } if (geo_ops.withcoord) { - (*cntx)->StartArray(2); - (*cntx)->SendDouble(p.longitude); - (*cntx)->SendDouble(p.latitude); + rb->StartArray(2); + rb->SendDouble(p.longitude); + rb->SendDouble(p.latitude); } } } @@ -2903,7 +2916,7 @@ void ZSetFamily::GeoSearch(CmdArgList args, ConnectionContext* cntx) { if (cur_arg == "FROMMEMBER") { if (from_set) { - return (*cntx)->SendError(kFromMemberLonglatErr); + return cntx->SendError(kFromMemberLonglatErr); } else if (i + 1 < args.size()) { string_view member; member = ArgS(args, i + 1); @@ -2914,19 +2927,19 @@ void ZSetFamily::GeoSearch(CmdArgList args, ConnectionContext* cntx) { }; OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - return (*cntx)->SendError(kWrongTypeErr); + return cntx->SendError(kWrongTypeErr); } else if (!result) { - return (*cntx)->SendError("Member not found"); + return cntx->SendError("Member not found"); } ScoreToLongLat(*result, shape.xy); from_set = true; i++; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } else if (cur_arg == "FROMLONLAT") { if (from_set) { - return (*cntx)->SendError(kFromMemberLonglatErr); + return cntx->SendError(kFromMemberLonglatErr); } else if (i + 2 < args.size()) { string_view longitude_str = ArgS(args, i + 1); string_view latitude_str = ArgS(args, i + 2); @@ -2934,65 +2947,65 @@ void ZSetFamily::GeoSearch(CmdArgList args, ConnectionContext* cntx) { if (!ParseLongLat(longitude_str, latitude_str, &longlat)) { string err = absl::StrCat("-ERR invalid longitude,latitude pair ", longitude_str, ",", latitude_str); - return (*cntx)->SendError(err, kSyntaxErrType); + return cntx->SendError(err, kSyntaxErrType); } shape.xy[0] = longlat.first; shape.xy[1] = longlat.second; from_set = true; i += 2; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } else if (cur_arg == "BYRADIUS") { if (by_set) { - return (*cntx)->SendError(kByRadiusBoxErr); + return cntx->SendError(kByRadiusBoxErr); } else if (i + 2 < args.size()) { if (!ParseDouble(ArgS(args, i + 1), &shape.t.radius)) { - return (*cntx)->SendError(kInvalidFloatErr); + return cntx->SendError(kInvalidFloatErr); } string_view unit = ArgS(args, i + 2); shape.conversion = ExtractUnit(unit); geo_ops.conversion = shape.conversion; if (shape.conversion == -1) { - return (*cntx)->SendError("unsupported unit provided. please use M, KM, FT, MI"); + return cntx->SendError("unsupported unit provided. please use M, KM, FT, MI"); } shape.type = CIRCULAR_TYPE; by_set = true; i += 2; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } else if (cur_arg == "BYBOX") { if (by_set) { - return (*cntx)->SendError(kByRadiusBoxErr); + return cntx->SendError(kByRadiusBoxErr); } else if (i + 3 < args.size()) { if (!ParseDouble(ArgS(args, i + 1), &shape.t.r.width)) { - return (*cntx)->SendError(kInvalidFloatErr); + return cntx->SendError(kInvalidFloatErr); } if (!ParseDouble(ArgS(args, i + 2), &shape.t.r.height)) { - return (*cntx)->SendError(kInvalidFloatErr); + return cntx->SendError(kInvalidFloatErr); } string_view unit = ArgS(args, i + 3); shape.conversion = ExtractUnit(unit); geo_ops.conversion = shape.conversion; if (shape.conversion == -1) { - return (*cntx)->SendError("unsupported unit provided. please use M, KM, FT, MI"); + return cntx->SendError("unsupported unit provided. please use M, KM, FT, MI"); } shape.type = RECTANGLE_TYPE; by_set = true; i += 3; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } else if (cur_arg == "ASC") { if (geo_ops.sorting != Sorting::kUnsorted) { - return (*cntx)->SendError(kAscDescErr); + return cntx->SendError(kAscDescErr); } else { geo_ops.sorting = Sorting::kAsc; } } else if (cur_arg == "DESC") { if (geo_ops.sorting != Sorting::kUnsorted) { - return (*cntx)->SendError(kAscDescErr); + return cntx->SendError(kAscDescErr); } else { geo_ops.sorting = Sorting::kDesc; } @@ -3001,7 +3014,7 @@ void ZSetFamily::GeoSearch(CmdArgList args, ConnectionContext* cntx) { absl::SimpleAtoi(std::string(ArgS(args, i + 1)), &geo_ops.count); i++; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } if (i + 1 < args.size() && ArgS(args, i + 1) == "ANY") { geo_ops.any = true; @@ -3014,16 +3027,16 @@ void ZSetFamily::GeoSearch(CmdArgList args, ConnectionContext* cntx) { } else if (cur_arg == "WITHHASH") geo_ops.withhash = true; else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } // check mandatory options if (!from_set) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } if (!by_set) { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } GeoSearchGeneric(cntx, shape, key, geo_ops); } @@ -3040,20 +3053,20 @@ void ZSetFamily::GeoRadiusByMember(CmdArgList args, ConnectionContext* cntx) { }; OpResult result = cntx->transaction->ScheduleSingleHopT(std::move(cb)); if (result.status() == OpStatus::WRONG_TYPE) { - return (*cntx)->SendError(kWrongTypeErr); + return cntx->SendError(kWrongTypeErr); } else if (!result) { - return (*cntx)->SendError("Member not found"); + return cntx->SendError("Member not found"); } ScoreToLongLat(*result, shape.xy); if (!ParseDouble(ArgS(args, 2), &shape.t.radius)) { - return (*cntx)->SendError(kInvalidFloatErr); + return cntx->SendError(kInvalidFloatErr); } string_view unit = ArgS(args, 3); shape.conversion = ExtractUnit(unit); geo_ops.conversion = shape.conversion; if (shape.conversion == -1) { - return (*cntx)->SendError("unsupported unit provided. please use M, KM, FT, MI"); + return cntx->SendError("unsupported unit provided. please use M, KM, FT, MI"); } shape.type = CIRCULAR_TYPE; string_view store_key; @@ -3064,13 +3077,13 @@ void ZSetFamily::GeoRadiusByMember(CmdArgList args, ConnectionContext* cntx) { string_view cur_arg = ArgS(args, i); if (cur_arg == "ASC") { if (geo_ops.sorting != Sorting::kUnsorted) { - return (*cntx)->SendError(kAscDescErr); + return cntx->SendError(kAscDescErr); } else { geo_ops.sorting = Sorting::kAsc; } } else if (cur_arg == "DESC") { if (geo_ops.sorting != Sorting::kUnsorted) { - return (*cntx)->SendError(kAscDescErr); + return cntx->SendError(kAscDescErr); } else { geo_ops.sorting = Sorting::kDesc; } @@ -3079,7 +3092,7 @@ void ZSetFamily::GeoRadiusByMember(CmdArgList args, ConnectionContext* cntx) { absl::SimpleAtoi(std::string(ArgS(args, i + 1)), &geo_ops.count); i++; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } if (i + 1 < args.size() && ArgS(args, i + 1) == "ANY") { geo_ops.any = true; @@ -3093,28 +3106,28 @@ void ZSetFamily::GeoRadiusByMember(CmdArgList args, ConnectionContext* cntx) { geo_ops.withhash = true; } else if (cur_arg == "STORE") { if (geo_ops.store != GeoStoreType::kNoStore) { - return (*cntx)->SendError(kStoreTypeErr); + return cntx->SendError(kStoreTypeErr); } if (i + 1 < args.size()) { store_key = ArgS(args, i + 1); geo_ops.store = GeoStoreType::kStoreHash; i++; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } else if (cur_arg == "STOREDIST") { if (geo_ops.store != GeoStoreType::kNoStore) { - return (*cntx)->SendError(kStoreTypeErr); + return cntx->SendError(kStoreTypeErr); } if (i + 1 < args.size()) { store_key = ArgS(args, i + 1); geo_ops.store = GeoStoreType::kStoreDist; i++; } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } else { - return (*cntx)->SendError(kSyntaxErr); + return cntx->SendError(kSyntaxErr); } } GeoSearchGeneric(cntx, shape, key, geo_ops);