mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-10 18:05:44 +02:00
Remove cmd name from args (#1057)
chore: remove cmd name from the list of arguments Signed-off-by: Vladislav Oleshko <vlad@dragonflydb.io> Co-authored-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
parent
8600eacdc4
commit
a12ddfe108
25 changed files with 564 additions and 573 deletions
|
@ -508,32 +508,32 @@ void BitPos(CmdArgList args, ConnectionContext* cntx) {
|
|||
// Support for the command BITPOS
|
||||
// See details at https://redis.io/commands/bitpos/
|
||||
|
||||
if (args.size() < 2 || args.size() > 6) {
|
||||
if (args.size() < 1 || args.size() > 5) {
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
|
||||
int32_t value{0};
|
||||
int64_t start = 0;
|
||||
int64_t end = std::numeric_limits<int64_t>::max();
|
||||
bool as_bit = false;
|
||||
|
||||
if (!absl::SimpleAtoi(ArgS(args, 2), &value)) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 1), &value)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
|
||||
if (args.size() >= 4) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 3), &start)) {
|
||||
if (args.size() >= 3) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 2), &start)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
if (args.size() >= 5) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 4), &end)) {
|
||||
if (args.size() >= 4) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 3), &end)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
|
||||
if (args.size() >= 6) {
|
||||
if (!ToUpperAndGetAsBit(args, 5, &as_bit)) {
|
||||
if (args.size() >= 5) {
|
||||
if (!ToUpperAndGetAsBit(args, 4, &as_bit)) {
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
}
|
||||
|
@ -553,21 +553,21 @@ void BitCount(CmdArgList args, ConnectionContext* cntx) {
|
|||
// See details at https://redis.io/commands/bitcount/
|
||||
// Please note that if the key don't exists, it would return 0
|
||||
|
||||
if (args.size() == 3 || args.size() > 5) {
|
||||
if (args.size() == 2 || args.size() > 4) {
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
// return (*cntx)->SendLong(0);
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
bool as_bit = false;
|
||||
int64_t start = 0;
|
||||
int64_t end = std::numeric_limits<int64_t>::max();
|
||||
if (args.size() >= 4) {
|
||||
if (absl::SimpleAtoi(ArgS(args, 2), &start) == 0 ||
|
||||
absl::SimpleAtoi(ArgS(args, 3), &end) == 0) {
|
||||
if (args.size() >= 3) {
|
||||
if (absl::SimpleAtoi(ArgS(args, 1), &start) == 0 ||
|
||||
absl::SimpleAtoi(ArgS(args, 2), &end) == 0) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
if (args.size() == 5) {
|
||||
if (!ToUpperAndGetAsBit(args, 4, &as_bit)) {
|
||||
if (args.size() == 4) {
|
||||
if (!ToUpperAndGetAsBit(args, 3, &as_bit)) {
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
}
|
||||
|
@ -591,13 +591,13 @@ void BitFieldRo(CmdArgList args, ConnectionContext* cntx) {
|
|||
void BitOp(CmdArgList args, ConnectionContext* cntx) {
|
||||
static const std::array<std::string_view, 4> BITOP_OP_NAMES{OR_OP_NAME, XOR_OP_NAME, AND_OP_NAME,
|
||||
NOT_OP_NAME};
|
||||
ToUpper(&args[1]);
|
||||
std::string_view op = ArgS(args, 1);
|
||||
std::string_view dest_key = ArgS(args, 2);
|
||||
ToUpper(&args[0]);
|
||||
std::string_view op = ArgS(args, 0);
|
||||
std::string_view dest_key = ArgS(args, 1);
|
||||
bool illegal = std::none_of(BITOP_OP_NAMES.begin(), BITOP_OP_NAMES.end(),
|
||||
[&op](auto val) { return op == val; });
|
||||
|
||||
if (illegal || (op == NOT_OP_NAME && args.size() > 4)) {
|
||||
if (illegal || (op == NOT_OP_NAME && args.size() > 3)) {
|
||||
return (*cntx)->SendError(kSyntaxErr); // too many arguments
|
||||
}
|
||||
|
||||
|
@ -658,9 +658,9 @@ void GetBit(CmdArgList args, ConnectionContext* cntx) {
|
|||
// see https://redis.io/commands/getbit/
|
||||
|
||||
uint32_t offset{0};
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
|
||||
if (!absl::SimpleAtoi(ArgS(args, 2), &offset)) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 1), &offset)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
|
@ -677,9 +677,9 @@ void SetBit(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
uint32_t offset{0};
|
||||
int32_t value{0};
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
|
||||
if (!absl::SimpleAtoi(ArgS(args, 2), &offset) || !absl::SimpleAtoi(ArgS(args, 3), &value)) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 1), &offset) || !absl::SimpleAtoi(ArgS(args, 2), &value)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,9 +53,9 @@ CommandRegistry::CommandRegistry() {
|
|||
}
|
||||
|
||||
void CommandRegistry::Command(CmdArgList args, ConnectionContext* cntx) {
|
||||
if (args.size() > 1) {
|
||||
ToUpper(&args[1]);
|
||||
string_view subcmd = ArgS(args, 1);
|
||||
if (args.size() > 0) {
|
||||
ToUpper(&args[0]);
|
||||
string_view subcmd = ArgS(args, 0);
|
||||
if (subcmd == "COUNT") {
|
||||
return (*cntx)->SendLong(cmd_map_.size());
|
||||
} else {
|
||||
|
|
|
@ -61,24 +61,24 @@ struct KeyIndex {
|
|||
unsigned end; // does not include this index (open limit).
|
||||
unsigned step; // 1 for commands like mget. 2 for commands like mset.
|
||||
|
||||
// if index is non-zero then adds another key index (usually 1).
|
||||
// if index is non-zero then adds another key index (usually 0).
|
||||
// relevant for for commands like ZUNIONSTORE/ZINTERSTORE for destination key.
|
||||
unsigned bonus = 0;
|
||||
std::optional<uint16_t> bonus{};
|
||||
|
||||
static KeyIndex Empty() {
|
||||
return KeyIndex{0, 0, 0, 0};
|
||||
return KeyIndex{0, 0, 0, std::nullopt};
|
||||
}
|
||||
|
||||
static KeyIndex Range(unsigned start, unsigned end, unsigned step = 1) {
|
||||
return KeyIndex{start, end, step, 0};
|
||||
return KeyIndex{start, end, step, std::nullopt};
|
||||
}
|
||||
|
||||
bool HasSingleKey() const {
|
||||
return bonus == 0 && (start + step >= end);
|
||||
return !bonus && (start + step >= end);
|
||||
}
|
||||
|
||||
unsigned num_args() const {
|
||||
return end - start + (bonus > 0);
|
||||
return end - start + bool(bonus);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ DebugCmd::DebugCmd(ServerFamily* owner, ConnectionContext* cntx) : sf_(*owner),
|
|||
}
|
||||
|
||||
void DebugCmd::Run(CmdArgList args) {
|
||||
string_view subcmd = ArgS(args, 1);
|
||||
string_view subcmd = ArgS(args, 0);
|
||||
if (subcmd == "HELP") {
|
||||
string_view help_arr[] = {
|
||||
"DEBUG <subcommand> [<arg> [value] [opt] ...]. Subcommands are:",
|
||||
|
@ -128,7 +128,7 @@ void DebugCmd::Run(CmdArgList args) {
|
|||
return Reload(args);
|
||||
}
|
||||
|
||||
if (subcmd == "REPLICA" && args.size() == 3) {
|
||||
if (subcmd == "REPLICA" && args.size() == 2) {
|
||||
return Replica(args);
|
||||
}
|
||||
|
||||
|
@ -136,12 +136,12 @@ void DebugCmd::Run(CmdArgList args) {
|
|||
return Watched();
|
||||
}
|
||||
|
||||
if (subcmd == "LOAD" && args.size() == 3) {
|
||||
return Load(ArgS(args, 2));
|
||||
if (subcmd == "LOAD" && args.size() == 2) {
|
||||
return Load(ArgS(args, 1));
|
||||
}
|
||||
|
||||
if (subcmd == "OBJECT" && args.size() == 3) {
|
||||
string_view key = ArgS(args, 2);
|
||||
if (subcmd == "OBJECT" && args.size() == 2) {
|
||||
string_view key = ArgS(args, 1);
|
||||
return Inspect(key);
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ void DebugCmd::Run(CmdArgList args) {
|
|||
void DebugCmd::Reload(CmdArgList args) {
|
||||
bool save = true;
|
||||
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
ToUpper(&args[i]);
|
||||
string_view opt = ArgS(args, i);
|
||||
VLOG(1) << "opt " << opt;
|
||||
|
@ -187,7 +187,7 @@ void DebugCmd::Reload(CmdArgList args) {
|
|||
}
|
||||
|
||||
void DebugCmd::Replica(CmdArgList args) {
|
||||
args.remove_prefix(2);
|
||||
args.remove_prefix(1);
|
||||
ToUpper(&args[0]);
|
||||
string_view opt = ArgS(args, 0);
|
||||
|
||||
|
@ -254,29 +254,29 @@ void DebugCmd::Load(string_view filename) {
|
|||
}
|
||||
|
||||
void DebugCmd::Populate(CmdArgList args) {
|
||||
if (args.size() < 3 || args.size() > 6) {
|
||||
if (args.size() < 2 || args.size() > 5) {
|
||||
return (*cntx_)->SendError(UnknownSubCmd("populate", "DEBUG"));
|
||||
}
|
||||
|
||||
uint64_t total_count = 0;
|
||||
if (!absl::SimpleAtoi(ArgS(args, 2), &total_count))
|
||||
if (!absl::SimpleAtoi(ArgS(args, 1), &total_count))
|
||||
return (*cntx_)->SendError(kUintErr);
|
||||
std::string_view prefix{"key"};
|
||||
|
||||
if (args.size() > 3) {
|
||||
prefix = ArgS(args, 3);
|
||||
if (args.size() > 2) {
|
||||
prefix = ArgS(args, 2);
|
||||
}
|
||||
uint32_t val_size = 0;
|
||||
if (args.size() > 4) {
|
||||
std::string_view str = ArgS(args, 4);
|
||||
if (args.size() > 3) {
|
||||
std::string_view str = ArgS(args, 3);
|
||||
if (!absl::SimpleAtoi(str, &val_size))
|
||||
return (*cntx_)->SendError(kUintErr);
|
||||
}
|
||||
|
||||
bool populate_random_values = false;
|
||||
if (args.size() > 5) {
|
||||
ToUpper(&args[5]);
|
||||
std::string_view str = ArgS(args, 5);
|
||||
if (args.size() > 4) {
|
||||
ToUpper(&args[4]);
|
||||
std::string_view str = ArgS(args, 4);
|
||||
if (str != "RAND") {
|
||||
return (*cntx_)->SendError(kSyntaxErr);
|
||||
}
|
||||
|
|
|
@ -88,11 +88,11 @@ DflyCmd::DflyCmd(util::ListenerInterface* listener, ServerFamily* server_family)
|
|||
void DflyCmd::Run(CmdArgList args, ConnectionContext* cntx) {
|
||||
RedisReplyBuilder* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
||||
|
||||
DCHECK_GE(args.size(), 2u);
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
DCHECK_GE(args.size(), 1u);
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
|
||||
if (sub_cmd == "JOURNAL" && args.size() >= 3) {
|
||||
if (sub_cmd == "JOURNAL" && args.size() >= 2) {
|
||||
return Journal(args, cntx);
|
||||
}
|
||||
|
||||
|
@ -100,15 +100,15 @@ void DflyCmd::Run(CmdArgList args, ConnectionContext* cntx) {
|
|||
return Thread(args, cntx);
|
||||
}
|
||||
|
||||
if (sub_cmd == "FLOW" && args.size() == 5) {
|
||||
if (sub_cmd == "FLOW" && args.size() == 4) {
|
||||
return Flow(args, cntx);
|
||||
}
|
||||
|
||||
if (sub_cmd == "SYNC" && args.size() == 3) {
|
||||
if (sub_cmd == "SYNC" && args.size() == 2) {
|
||||
return Sync(args, cntx);
|
||||
}
|
||||
|
||||
if (sub_cmd == "STARTSTABLE" && args.size() == 3) {
|
||||
if (sub_cmd == "STARTSTABLE" && args.size() == 2) {
|
||||
return StartStable(args, cntx);
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ void DflyCmd::Run(CmdArgList args, ConnectionContext* cntx) {
|
|||
return Expire(args, cntx);
|
||||
}
|
||||
|
||||
if (sub_cmd == "REPLICAOFFSET" && args.size() == 3) {
|
||||
if (sub_cmd == "REPLICAOFFSET" && args.size() == 2) {
|
||||
return ReplicaOffset(args, cntx);
|
||||
}
|
||||
|
||||
|
@ -124,10 +124,10 @@ void DflyCmd::Run(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void DflyCmd::Journal(CmdArgList args, ConnectionContext* cntx) {
|
||||
DCHECK_GE(args.size(), 3u);
|
||||
ToUpper(&args[2]);
|
||||
DCHECK_GE(args.size(), 2u);
|
||||
ToUpper(&args[1]);
|
||||
|
||||
std::string_view sub_cmd = ArgS(args, 2);
|
||||
std::string_view sub_cmd = ArgS(args, 1);
|
||||
Transaction* trans = cntx->transaction;
|
||||
DCHECK(trans);
|
||||
RedisReplyBuilder* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
||||
|
@ -190,7 +190,7 @@ void DflyCmd::Thread(CmdArgList args, ConnectionContext* cntx) {
|
|||
RedisReplyBuilder* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
||||
util::ProactorPool* pool = shard_set->pool();
|
||||
|
||||
if (args.size() == 2) { // DFLY THREAD : returns connection thread index and number of threads.
|
||||
if (args.size() == 1) { // DFLY THREAD : returns connection thread index and number of threads.
|
||||
rb->StartArray(2);
|
||||
rb->SendLong(ProactorBase::GetIndex());
|
||||
rb->SendLong(long(pool->size()));
|
||||
|
@ -198,7 +198,7 @@ void DflyCmd::Thread(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
// DFLY THREAD to_thread : migrates current connection to a different thread.
|
||||
string_view arg = ArgS(args, 2);
|
||||
string_view arg = ArgS(args, 1);
|
||||
unsigned num_thread;
|
||||
if (!absl::SimpleAtoi(arg, &num_thread)) {
|
||||
return rb->SendError(kSyntaxErr);
|
||||
|
@ -217,9 +217,9 @@ void DflyCmd::Thread(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void DflyCmd::Flow(CmdArgList args, ConnectionContext* cntx) {
|
||||
RedisReplyBuilder* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
||||
string_view master_id = ArgS(args, 2);
|
||||
string_view sync_id_str = ArgS(args, 3);
|
||||
string_view flow_id_str = ArgS(args, 4);
|
||||
string_view master_id = ArgS(args, 1);
|
||||
string_view sync_id_str = ArgS(args, 2);
|
||||
string_view flow_id_str = ArgS(args, 3);
|
||||
|
||||
VLOG(1) << "Got DFLY FLOW " << master_id << " " << sync_id_str << " " << flow_id_str;
|
||||
|
||||
|
@ -259,7 +259,7 @@ void DflyCmd::Flow(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void DflyCmd::Sync(CmdArgList args, ConnectionContext* cntx) {
|
||||
RedisReplyBuilder* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
||||
string_view sync_id_str = ArgS(args, 2);
|
||||
string_view sync_id_str = ArgS(args, 1);
|
||||
|
||||
VLOG(1) << "Got DFLY SYNC " << sync_id_str;
|
||||
|
||||
|
@ -297,7 +297,7 @@ void DflyCmd::Sync(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void DflyCmd::StartStable(CmdArgList args, ConnectionContext* cntx) {
|
||||
RedisReplyBuilder* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
||||
string_view sync_id_str = ArgS(args, 2);
|
||||
string_view sync_id_str = ArgS(args, 1);
|
||||
|
||||
VLOG(1) << "Got DFLY STARTSTABLE " << sync_id_str;
|
||||
|
||||
|
@ -346,7 +346,7 @@ void DflyCmd::Expire(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void DflyCmd::ReplicaOffset(CmdArgList args, ConnectionContext* cntx) {
|
||||
RedisReplyBuilder* rb = static_cast<RedisReplyBuilder*>(cntx->reply_builder());
|
||||
string_view sync_id_str = ArgS(args, 2);
|
||||
string_view sync_id_str = ArgS(args, 1);
|
||||
|
||||
VLOG(1) << "Got DFLY REPLICAOFFSET " << sync_id_str;
|
||||
auto [sync_id, replica_ptr] = GetReplicaInfoOrReply(sync_id_str, rb);
|
||||
|
|
|
@ -214,15 +214,14 @@ class RestoreArgs {
|
|||
}
|
||||
|
||||
// The structure that we are expecting is:
|
||||
// args[0] == "RESTORE"
|
||||
// args[1] == "key"
|
||||
// args[2] == "ttl"
|
||||
// args[3] == serialized value (list of chars that are used for the actual restore).
|
||||
// args[4] .. args[n]: optional arguments that can be [REPLACE] [ABSTTL] [IDLETIME seconds]
|
||||
// args[0] == "key"
|
||||
// args[1] == "ttl"
|
||||
// args[2] == serialized value (list of chars that are used for the actual restore).
|
||||
// args[3] .. args[n]: optional arguments that can be [REPLACE] [ABSTTL] [IDLETIME seconds]
|
||||
// [FREQ frequency], in any order
|
||||
OpResult<RestoreArgs> RestoreArgs::TryFrom(const CmdArgList& args) {
|
||||
RestoreArgs out_args;
|
||||
std::string_view cur_arg = ArgS(args, 2); // extract ttl
|
||||
std::string_view cur_arg = ArgS(args, 1); // extract ttl
|
||||
if (!absl::SimpleAtoi(cur_arg, &out_args.expiration_) || (out_args.expiration_ < 0)) {
|
||||
return OpStatus::INVALID_INT;
|
||||
}
|
||||
|
@ -234,7 +233,7 @@ OpResult<RestoreArgs> RestoreArgs::TryFrom(const CmdArgList& args) {
|
|||
// we would parse them and ensure that they are correct, maybe later they will be used
|
||||
int64_t idle_time = 0;
|
||||
|
||||
for (size_t i = 4; i < args.size(); ++i) {
|
||||
for (size_t i = 3; i < args.size(); ++i) {
|
||||
ToUpper(&args[i]);
|
||||
cur_arg = ArgS(args, i);
|
||||
bool additional = args.size() - i - 1 >= 1;
|
||||
|
@ -635,7 +634,7 @@ void GenericFamily::Shutdown() {
|
|||
|
||||
void GenericFamily::Del(CmdArgList args, ConnectionContext* cntx) {
|
||||
Transaction* transaction = cntx->transaction;
|
||||
VLOG(1) << "Del " << ArgS(args, 1);
|
||||
VLOG(1) << "Del " << ArgS(args, 0);
|
||||
|
||||
atomic_uint32_t result{0};
|
||||
bool is_mc = cntx->protocol() == Protocol::MEMCACHE;
|
||||
|
@ -669,16 +668,16 @@ void GenericFamily::Del(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::Ping(CmdArgList args, ConnectionContext* cntx) {
|
||||
if (args.size() > 2) {
|
||||
if (args.size() > 1) {
|
||||
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() == 1) {
|
||||
if (args.size() == 0) {
|
||||
return (*cntx)->SendSimpleString("PONG");
|
||||
} else {
|
||||
string_view arg = ArgS(args, 1);
|
||||
string_view arg = ArgS(args, 0);
|
||||
DVLOG(2) << "Ping " << arg;
|
||||
|
||||
return (*cntx)->SendBulkString(arg);
|
||||
|
@ -687,7 +686,7 @@ void GenericFamily::Ping(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void GenericFamily::Exists(CmdArgList args, ConnectionContext* cntx) {
|
||||
Transaction* transaction = cntx->transaction;
|
||||
VLOG(1) << "Exists " << ArgS(args, 1);
|
||||
VLOG(1) << "Exists " << ArgS(args, 0);
|
||||
|
||||
atomic_uint32_t result{0};
|
||||
|
||||
|
@ -706,7 +705,7 @@ void GenericFamily::Exists(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::Persist(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) { return OpPersist(t->GetOpArgs(shard), key); };
|
||||
|
||||
|
@ -715,8 +714,8 @@ void GenericFamily::Persist(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::Expire(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view sec = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view sec = ArgS(args, 1);
|
||||
int64_t int_arg;
|
||||
|
||||
if (!absl::SimpleAtoi(sec, &int_arg)) {
|
||||
|
@ -740,8 +739,8 @@ void GenericFamily::Expire(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::ExpireAt(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view sec = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view sec = ArgS(args, 1);
|
||||
int64_t int_arg;
|
||||
|
||||
if (!absl::SimpleAtoi(sec, &int_arg)) {
|
||||
|
@ -764,7 +763,7 @@ void GenericFamily::ExpireAt(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::Keys(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view pattern(ArgS(args, 1));
|
||||
string_view pattern(ArgS(args, 0));
|
||||
uint64_t cursor = 0;
|
||||
|
||||
StringVec keys;
|
||||
|
@ -785,8 +784,8 @@ void GenericFamily::Keys(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::PexpireAt(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view msec = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view msec = ArgS(args, 1);
|
||||
int64_t int_arg;
|
||||
|
||||
if (!absl::SimpleAtoi(msec, &int_arg)) {
|
||||
|
@ -808,8 +807,8 @@ void GenericFamily::PexpireAt(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::Pexpire(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view msec = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view msec = ArgS(args, 1);
|
||||
int64_t int_arg;
|
||||
|
||||
if (!absl::SimpleAtoi(msec, &int_arg)) {
|
||||
|
@ -832,7 +831,7 @@ void GenericFamily::Pexpire(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void GenericFamily::Stick(CmdArgList args, ConnectionContext* cntx) {
|
||||
Transaction* transaction = cntx->transaction;
|
||||
VLOG(1) << "Stick " << ArgS(args, 1);
|
||||
VLOG(1) << "Stick " << ArgS(args, 0);
|
||||
|
||||
atomic_uint32_t result{0};
|
||||
|
||||
|
@ -953,12 +952,12 @@ OpResultTyped<SortEntryList> OpFetchSortEntries(const OpArgs& op_args, std::stri
|
|||
}
|
||||
|
||||
void GenericFamily::Sort(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
bool alpha = false;
|
||||
bool reversed = false;
|
||||
std::optional<std::pair<size_t, size_t>> bounds;
|
||||
|
||||
for (size_t i = 2; i < args.size(); i++) {
|
||||
for (size_t i = 1; i < args.size(); i++) {
|
||||
ToUpper(&args[i]);
|
||||
|
||||
std::string_view arg = ArgS(args, i);
|
||||
|
@ -1024,8 +1023,8 @@ void GenericFamily::Sort(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::Restore(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view serialized_value = ArgS(args, 3);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
std::string_view serialized_value = ArgS(args, 2);
|
||||
|
||||
if (!VerifyFooter(serialized_value)) {
|
||||
return (*cntx)->SendError("ERR DUMP payload version or checksum are wrong");
|
||||
|
@ -1065,8 +1064,8 @@ void GenericFamily::Restore(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::Move(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view target_db_sv = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view target_db_sv = ArgS(args, 1);
|
||||
int64_t target_db;
|
||||
|
||||
if (!absl::SimpleAtoi(target_db_sv, &target_db)) {
|
||||
|
@ -1129,7 +1128,7 @@ void GenericFamily::Pttl(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::TtlGeneric(CmdArgList args, ConnectionContext* cntx, TimeUnit unit) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) { return OpTtl(t, shard, key); };
|
||||
OpResult<uint64_t> result = cntx->transaction->ScheduleSingleHopT(std::move(cb));
|
||||
|
@ -1153,7 +1152,7 @@ void GenericFamily::TtlGeneric(CmdArgList args, ConnectionContext* cntx, TimeUni
|
|||
}
|
||||
|
||||
void GenericFamily::Select(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
int64_t index;
|
||||
if (!absl::SimpleAtoi(key, &index)) {
|
||||
return (*cntx)->SendError(kInvalidDbIndErr);
|
||||
|
@ -1172,7 +1171,7 @@ void GenericFamily::Select(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::Dump(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
DVLOG(1) << "Dumping before ::ScheduleSingleHopT " << key;
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) { return OpDump(t->GetOpArgs(shard), key); };
|
||||
|
||||
|
@ -1189,7 +1188,7 @@ void GenericFamily::Dump(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void GenericFamily::Type(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<int> {
|
||||
auto it = shard->db_slice().FindExt(t->GetDbContext(), key).first;
|
||||
|
@ -1222,7 +1221,7 @@ void GenericFamily::Time(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
OpResult<void> GenericFamily::RenameGeneric(CmdArgList args, bool skip_exist_dest,
|
||||
ConnectionContext* cntx) {
|
||||
string_view key[2] = {ArgS(args, 1), ArgS(args, 2)};
|
||||
string_view key[2] = {ArgS(args, 0), ArgS(args, 1)};
|
||||
|
||||
Transaction* transaction = cntx->transaction;
|
||||
|
||||
|
@ -1252,19 +1251,19 @@ OpResult<void> GenericFamily::RenameGeneric(CmdArgList args, bool skip_exist_des
|
|||
}
|
||||
|
||||
void GenericFamily::Echo(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
return (*cntx)->SendBulkString(key);
|
||||
}
|
||||
|
||||
void GenericFamily::Scan(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view token = ArgS(args, 1);
|
||||
string_view token = ArgS(args, 0);
|
||||
uint64_t cursor = 0;
|
||||
|
||||
if (!absl::SimpleAtoi(token, &cursor)) {
|
||||
return (*cntx)->SendError("invalid cursor");
|
||||
}
|
||||
|
||||
OpResult<ScanOpts> ops = ScanOpts::TryFrom(args.subspan(2));
|
||||
OpResult<ScanOpts> ops = ScanOpts::TryFrom(args.subspan(1));
|
||||
if (!ops) {
|
||||
DVLOG(1) << "Scan invalid args - return " << ops << " to the user";
|
||||
return (*cntx)->SendError(ops.status());
|
||||
|
|
|
@ -688,7 +688,7 @@ OpResult<uint32_t> OpSet(const OpArgs& op_args, string_view key, CmdArgList valu
|
|||
}
|
||||
|
||||
void HGetGeneric(CmdArgList args, ConnectionContext* cntx, uint8_t getall_mask) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpGetAll(t->GetOpArgs(shard), key, getall_mask);
|
||||
|
@ -707,16 +707,12 @@ void HGetGeneric(CmdArgList args, ConnectionContext* cntx, uint8_t getall_mask)
|
|||
|
||||
// HSETEX key tll_sec field value field value ...
|
||||
void HSetEx(CmdArgList args, ConnectionContext* cntx) {
|
||||
if (args.size() % 2 != 1) {
|
||||
ToLower(&args[0]);
|
||||
|
||||
string_view cmd = ArgS(args, 0);
|
||||
|
||||
return (*cntx)->SendError(facade::WrongNumArgsError(cmd), kSyntaxErrType);
|
||||
if (args.size() % 2 != 0) {
|
||||
return (*cntx)->SendError(facade::WrongNumArgsError(cntx->cid->name()), kSyntaxErrType);
|
||||
}
|
||||
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view ttl_str = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view ttl_str = ArgS(args, 1);
|
||||
uint32_t ttl_sec;
|
||||
constexpr uint32_t kMaxTtl = (1UL << 26);
|
||||
|
||||
|
@ -724,7 +720,7 @@ void HSetEx(CmdArgList args, ConnectionContext* cntx) {
|
|||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
|
||||
args.remove_prefix(3);
|
||||
args.remove_prefix(2);
|
||||
OpSetParams op_sp;
|
||||
op_sp.ttl = ttl_sec;
|
||||
|
||||
|
@ -743,9 +739,9 @@ void HSetEx(CmdArgList args, ConnectionContext* cntx) {
|
|||
} // namespace
|
||||
|
||||
void HSetFamily::HDel(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
args.remove_prefix(2);
|
||||
args.remove_prefix(1);
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpDel(t->GetOpArgs(shard), key, args);
|
||||
};
|
||||
|
@ -759,7 +755,7 @@ void HSetFamily::HDel(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HLen(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) { return OpLen(t->GetOpArgs(shard), key); };
|
||||
|
||||
|
@ -772,8 +768,8 @@ void HSetFamily::HLen(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HExists(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view field = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view field = ArgS(args, 1);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<int> {
|
||||
return OpExist(t->GetOpArgs(shard), key, field);
|
||||
|
@ -788,9 +784,9 @@ void HSetFamily::HExists(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HMGet(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
args.remove_prefix(2);
|
||||
args.remove_prefix(1);
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpMGet(t->GetOpArgs(shard), key, args);
|
||||
};
|
||||
|
@ -817,8 +813,8 @@ void HSetFamily::HMGet(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HGet(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view field = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view field = ArgS(args, 1);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpGet(t->GetOpArgs(shard), key, field);
|
||||
|
@ -837,9 +833,9 @@ void HSetFamily::HGet(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HIncrBy(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view field = ArgS(args, 2);
|
||||
string_view incrs = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view field = ArgS(args, 1);
|
||||
string_view incrs = ArgS(args, 2);
|
||||
int64_t ival = 0;
|
||||
|
||||
if (!absl::SimpleAtoi(incrs, &ival)) {
|
||||
|
@ -872,9 +868,9 @@ void HSetFamily::HIncrBy(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HIncrByFloat(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view field = ArgS(args, 2);
|
||||
string_view incrs = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view field = ArgS(args, 1);
|
||||
string_view incrs = ArgS(args, 2);
|
||||
double dval = 0;
|
||||
|
||||
if (!absl::SimpleAtod(incrs, &dval)) {
|
||||
|
@ -916,8 +912,8 @@ void HSetFamily::HGetAll(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HScan(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view token = ArgS(args, 2);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
std::string_view token = ArgS(args, 1);
|
||||
|
||||
uint64_t cursor = 0;
|
||||
|
||||
|
@ -926,12 +922,12 @@ void HSetFamily::HScan(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
// HSCAN key cursor [MATCH pattern] [COUNT count]
|
||||
if (args.size() > 7) {
|
||||
if (args.size() > 6) {
|
||||
DVLOG(1) << "got " << args.size() << " this is more than it should be";
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
|
||||
OpResult<ScanOpts> ops = ScanOpts::TryFrom(args.subspan(3));
|
||||
OpResult<ScanOpts> ops = ScanOpts::TryFrom(args.subspan(2));
|
||||
if (!ops) {
|
||||
DVLOG(1) << "HScan invalid args - return " << ops << " to the user";
|
||||
return (*cntx)->SendError(ops.status());
|
||||
|
@ -957,22 +953,22 @@ void HSetFamily::HScan(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HSet(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
ToLower(&args[0]);
|
||||
|
||||
string_view cmd = ArgS(args, 0);
|
||||
|
||||
if (args.size() % 2 != 0) {
|
||||
return (*cntx)->SendError(facade::WrongNumArgsError(cmd), kSyntaxErrType);
|
||||
if (args.size() % 2 != 1) {
|
||||
return (*cntx)->SendError(facade::WrongNumArgsError("hset"), kSyntaxErrType);
|
||||
}
|
||||
|
||||
args.remove_prefix(2);
|
||||
args.remove_prefix(1);
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpSet(t->GetOpArgs(shard), key, args);
|
||||
};
|
||||
|
||||
OpResult<uint32_t> result = cntx->transaction->ScheduleSingleHopT(std::move(cb));
|
||||
if (result && cmd == "hset") {
|
||||
string_view cmd{cntx->cid->name()};
|
||||
|
||||
if (result && cmd == "HSET") {
|
||||
(*cntx)->SendLong(*result);
|
||||
} else {
|
||||
(*cntx)->SendError(result.status());
|
||||
|
@ -980,9 +976,9 @@ void HSetFamily::HSet(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HSetNx(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
args.remove_prefix(2);
|
||||
args.remove_prefix(1);
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpSet(t->GetOpArgs(shard), key, args, OpSetParams{.skip_if_exists = true});
|
||||
};
|
||||
|
@ -996,8 +992,8 @@ void HSetFamily::HSetNx(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HStrLen(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view field = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view field = ArgS(args, 1);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpStrLen(t->GetOpArgs(shard), key, field);
|
||||
|
@ -1012,7 +1008,7 @@ void HSetFamily::HStrLen(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void HSetFamily::HRandField(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<StringVec> {
|
||||
auto& db_slice = shard->db_slice();
|
||||
|
|
|
@ -32,18 +32,7 @@ void JournalWriter::Write(std::string_view sv) {
|
|||
sink_->Write(io::Buffer(sv));
|
||||
}
|
||||
|
||||
void JournalWriter::Write(CmdArgList args) {
|
||||
Write(args.size());
|
||||
size_t cmd_size = 0;
|
||||
for (auto v : args) {
|
||||
cmd_size += v.size();
|
||||
}
|
||||
Write(cmd_size);
|
||||
for (auto v : args)
|
||||
Write(facade::ToSV(v));
|
||||
}
|
||||
|
||||
void JournalWriter::Write(std::pair<std::string_view, ArgSlice> args) {
|
||||
template <typename C> void JournalWriter::Write(std::pair<std::string_view, C> args) {
|
||||
auto [cmd, tail_args] = args;
|
||||
|
||||
Write(1 + tail_args.size());
|
||||
|
@ -55,10 +44,17 @@ void JournalWriter::Write(std::pair<std::string_view, ArgSlice> args) {
|
|||
Write(cmd_size);
|
||||
|
||||
Write(cmd);
|
||||
for (auto v : tail_args)
|
||||
Write(v);
|
||||
for (auto v : tail_args) {
|
||||
if constexpr (is_same_v<C, CmdArgList>)
|
||||
Write(facade::ToSV(v));
|
||||
else
|
||||
Write(v);
|
||||
}
|
||||
}
|
||||
|
||||
template void JournalWriter::Write(pair<string_view, CmdArgList>);
|
||||
template void JournalWriter::Write(pair<string_view, ArgSlice>);
|
||||
|
||||
void JournalWriter::Write(std::monostate) {
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,9 @@ class JournalWriter {
|
|||
private:
|
||||
void Write(uint64_t v); // Write packed unsigned integer.
|
||||
void Write(std::string_view sv); // Write string.
|
||||
void Write(CmdArgList args);
|
||||
void Write(std::pair<std::string_view, ArgSlice> args);
|
||||
|
||||
template <typename C> // CmdArgList or ArgSlice.
|
||||
void Write(std::pair<std::string_view, C> args);
|
||||
|
||||
void Write(std::monostate); // Overload for empty std::variant
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ struct EntryBase {
|
|||
struct Entry : public EntryBase {
|
||||
// Payload represents a non-owning view into a command executed on the shard.
|
||||
using Payload =
|
||||
std::variant<std::monostate, // No payload.
|
||||
CmdArgList, // Parts of a full command.
|
||||
std::pair<std::string_view, ArgSlice> // Command and its shard parts.
|
||||
std::variant<std::monostate, // No payload.
|
||||
std::pair<std::string_view, CmdArgList>, // Parts of a full command.
|
||||
std::pair<std::string_view, ArgSlice> // Command and its shard parts.
|
||||
>;
|
||||
|
||||
Entry(TxId txid, Op opcode, DbIndex dbid, uint32_t shard_cnt, Payload pl)
|
||||
|
|
|
@ -18,6 +18,13 @@ struct EntryPayloadVisitor {
|
|||
*out += ' ';
|
||||
}
|
||||
|
||||
void operator()(const CmdArgList list) {
|
||||
for (auto arg : list) {
|
||||
*out += facade::ToSV(arg);
|
||||
*out += ' ';
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(const ArgSlice slice) {
|
||||
for (auto arg : slice) {
|
||||
*out += arg;
|
||||
|
@ -25,18 +32,11 @@ struct EntryPayloadVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
void operator()(const pair<string_view, ArgSlice> p) {
|
||||
template <typename C> void operator()(const pair<string_view, C> p) {
|
||||
(*this)(p.first);
|
||||
(*this)(p.second);
|
||||
}
|
||||
|
||||
void operator()(const CmdArgList list) {
|
||||
for (auto arg : list) {
|
||||
*out += facade::ToSV(arg);
|
||||
*out += ' ';
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(monostate) {
|
||||
}
|
||||
|
||||
|
@ -100,12 +100,12 @@ TEST(Journal, WriteRead) {
|
|||
std::vector<journal::Entry> test_entries = {
|
||||
{0, journal::Op::COMMAND, 0, 2, make_pair("MSET", slice("A", "1", "B", "2"))},
|
||||
{0, journal::Op::COMMAND, 0, 2, make_pair("MSET", slice("C", "3"))},
|
||||
{1, journal::Op::COMMAND, 0, 2, list("DEL", "A", "B")},
|
||||
{2, journal::Op::COMMAND, 1, 1, list("LPUSH", "l", "v1", "v2")},
|
||||
{1, journal::Op::COMMAND, 0, 2, make_pair("DEL", list("A", "B"))},
|
||||
{2, journal::Op::COMMAND, 1, 1, make_pair("LPUSH", list("l", "v1", "v2"))},
|
||||
{3, journal::Op::COMMAND, 0, 1, make_pair("MSET", slice("D", "4"))},
|
||||
{4, journal::Op::COMMAND, 1, 1, list("DEL", "l1")},
|
||||
{5, journal::Op::COMMAND, 2, 1, list("SET", "E", "2")},
|
||||
{6, journal::Op::MULTI_COMMAND, 2, 1, list("SET", "E", "2")},
|
||||
{4, journal::Op::COMMAND, 1, 1, make_pair("DEL", list("l1"))},
|
||||
{5, journal::Op::COMMAND, 2, 1, make_pair("DEL", list("E", "2"))},
|
||||
{6, journal::Op::MULTI_COMMAND, 2, 1, make_pair("SET", list("E", "2"))},
|
||||
{6, journal::Op::EXEC, 2, 1}};
|
||||
|
||||
// Write all entries to a buffer.
|
||||
|
|
|
@ -1002,9 +1002,9 @@ OpResult<bool> OpSet(const OpArgs& op_args, string_view key, string_view path,
|
|||
} // namespace
|
||||
|
||||
void JsonFamily::Set(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view json_str = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
string_view json_str = ArgS(args, 2);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpSet(t->GetOpArgs(shard), key, path, json_str);
|
||||
|
@ -1025,10 +1025,10 @@ void JsonFamily::Set(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::Resp(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = DefaultJsonPath;
|
||||
if (args.size() > 2) {
|
||||
path = ArgS(args, 2);
|
||||
if (args.size() > 1) {
|
||||
path = ArgS(args, 1);
|
||||
}
|
||||
|
||||
error_code ec;
|
||||
|
@ -1059,7 +1059,7 @@ void JsonFamily::Resp(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void JsonFamily::Debug(CmdArgList args, ConnectionContext* cntx) {
|
||||
function<decltype(OpFields)> func;
|
||||
string_view command = ArgS(args, 1);
|
||||
string_view command = ArgS(args, 0);
|
||||
// The 'MEMORY' sub-command is not supported yet, calling to operation function should be added
|
||||
// here.
|
||||
if (absl::EqualsIgnoreCase(command, "help")) {
|
||||
|
@ -1077,14 +1077,14 @@ void JsonFamily::Debug(CmdArgList args, ConnectionContext* cntx) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (args.size() < 4) {
|
||||
(*cntx)->SendError(facade::WrongNumArgsError(command), facade::kSyntaxErrType);
|
||||
if (args.size() < 3) {
|
||||
(*cntx)->SendError(facade::WrongNumArgsError(cntx->cid->name()), facade::kSyntaxErrType);
|
||||
return;
|
||||
}
|
||||
|
||||
error_code ec;
|
||||
string_view key = ArgS(args, 2);
|
||||
string_view path = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
JsonExpression expression = jsonpath::make_expression<JsonType>(path, ec);
|
||||
|
||||
if (ec) {
|
||||
|
@ -1108,7 +1108,7 @@ void JsonFamily::Debug(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::MGet(CmdArgList args, ConnectionContext* cntx) {
|
||||
DCHECK_GE(args.size(), 2U);
|
||||
DCHECK_GE(args.size(), 1U);
|
||||
|
||||
error_code ec;
|
||||
string_view path = ArgS(args, args.size() - 1);
|
||||
|
@ -1133,7 +1133,7 @@ void JsonFamily::MGet(CmdArgList args, ConnectionContext* cntx) {
|
|||
OpStatus result = transaction->ScheduleSingleHop(std::move(cb));
|
||||
CHECK_EQ(OpStatus::OK, result);
|
||||
|
||||
std::vector<OptString> results(args.size() - 2);
|
||||
std::vector<OptString> results(args.size() - 1);
|
||||
for (ShardId sid = 0; sid < shard_count; ++sid) {
|
||||
if (!transaction->IsActive(sid))
|
||||
continue;
|
||||
|
@ -1164,8 +1164,8 @@ void JsonFamily::MGet(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::ArrIndex(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
|
||||
error_code ec;
|
||||
JsonExpression expression = jsonpath::make_expression<JsonType>(path, ec);
|
||||
|
@ -1176,7 +1176,7 @@ void JsonFamily::ArrIndex(CmdArgList args, ConnectionContext* cntx) {
|
|||
return;
|
||||
}
|
||||
|
||||
optional<JsonType> search_value = JsonFromString(ArgS(args, 3));
|
||||
optional<JsonType> search_value = JsonFromString(ArgS(args, 2));
|
||||
if (!search_value) {
|
||||
(*cntx)->SendError(kSyntaxErr);
|
||||
return;
|
||||
|
@ -1188,18 +1188,18 @@ void JsonFamily::ArrIndex(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
int start_index = 0;
|
||||
if (args.size() >= 5) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 4), &start_index)) {
|
||||
VLOG(1) << "Failed to convert the start index to numeric" << ArgS(args, 4);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int end_index = 0;
|
||||
if (args.size() >= 6) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 5), &end_index)) {
|
||||
VLOG(1) << "Failed to convert the stop index to numeric" << ArgS(args, 5);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -1221,18 +1221,18 @@ void JsonFamily::ArrIndex(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::ArrInsert(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
int index = -1;
|
||||
|
||||
if (!absl::SimpleAtoi(ArgS(args, 3), &index)) {
|
||||
VLOG(1) << "Failed to convert the following value to numeric: " << ArgS(args, 3);
|
||||
if (!absl::SimpleAtoi(ArgS(args, 2), &index)) {
|
||||
VLOG(1) << "Failed to convert the following value to numeric: " << ArgS(args, 2);
|
||||
(*cntx)->SendError(kInvalidIntErr);
|
||||
return;
|
||||
}
|
||||
|
||||
vector<JsonType> new_values;
|
||||
for (size_t i = 4; i < args.size(); i++) {
|
||||
for (size_t i = 3; i < args.size(); i++) {
|
||||
optional<JsonType> val = JsonFromString(ArgS(args, i));
|
||||
if (!val) {
|
||||
(*cntx)->SendError(kSyntaxErr);
|
||||
|
@ -1256,10 +1256,10 @@ void JsonFamily::ArrInsert(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::ArrAppend(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
vector<JsonType> append_values;
|
||||
for (size_t i = 3; i < args.size(); ++i) {
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
optional<JsonType> converted_val = JsonFromString(ArgS(args, i));
|
||||
if (!converted_val) {
|
||||
(*cntx)->SendError(kSyntaxErr);
|
||||
|
@ -1288,18 +1288,18 @@ void JsonFamily::ArrAppend(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::ArrTrim(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
int start_index;
|
||||
int stop_index;
|
||||
|
||||
if (!absl::SimpleAtoi(ArgS(args, 3), &start_index)) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 2), &start_index)) {
|
||||
VLOG(1) << "Failed to parse array start index";
|
||||
(*cntx)->SendError(kInvalidIntErr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!absl::SimpleAtoi(ArgS(args, 4), &stop_index)) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 3), &stop_index)) {
|
||||
VLOG(1) << "Failed to parse array stop index";
|
||||
(*cntx)->SendError(kInvalidIntErr);
|
||||
return;
|
||||
|
@ -1324,14 +1324,14 @@ void JsonFamily::ArrTrim(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::ArrPop(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
int index = -1;
|
||||
|
||||
if (args.size() >= 4) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 3), &index)) {
|
||||
if (args.size() >= 3) {
|
||||
if (!absl::SimpleAtoi(ArgS(args, 2), &index)) {
|
||||
VLOG(1) << "Failed to convert the following value to numeric, pop out the last item"
|
||||
<< ArgS(args, 3);
|
||||
<< ArgS(args, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1365,8 +1365,8 @@ void JsonFamily::ArrPop(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::Clear(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpClear(t->GetOpArgs(shard), key, path);
|
||||
|
@ -1383,11 +1383,11 @@ void JsonFamily::Clear(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::StrAppend(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
|
||||
vector<string_view> strs;
|
||||
for (size_t i = 3; i < args.size(); ++i) {
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
strs.emplace_back(ArgS(args, i));
|
||||
}
|
||||
|
||||
|
@ -1406,8 +1406,8 @@ void JsonFamily::StrAppend(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::ObjKeys(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
|
||||
error_code ec;
|
||||
JsonExpression expression = jsonpath::make_expression<JsonType>(path, ec);
|
||||
|
@ -1440,10 +1440,10 @@ void JsonFamily::ObjKeys(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::Del(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path;
|
||||
if (args.size() > 2) {
|
||||
path = ArgS(args, 2);
|
||||
if (args.size() > 1) {
|
||||
path = ArgS(args, 1);
|
||||
}
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
|
@ -1456,9 +1456,9 @@ void JsonFamily::Del(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::NumIncrBy(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view num = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
string_view num = ArgS(args, 2);
|
||||
|
||||
double dnum;
|
||||
if (!ParseDouble(num, &dnum)) {
|
||||
|
@ -1481,9 +1481,9 @@ void JsonFamily::NumIncrBy(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::NumMultBy(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view num = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
string_view num = ArgS(args, 2);
|
||||
|
||||
double dnum;
|
||||
if (!ParseDouble(num, &dnum)) {
|
||||
|
@ -1506,8 +1506,8 @@ void JsonFamily::NumMultBy(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::Toggle(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpToggle(t->GetOpArgs(shard), key, path);
|
||||
|
@ -1524,8 +1524,8 @@ void JsonFamily::Toggle(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::Type(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
|
||||
error_code ec;
|
||||
JsonExpression expression = jsonpath::make_expression<JsonType>(path, ec);
|
||||
|
@ -1560,8 +1560,8 @@ void JsonFamily::Type(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::ArrLen(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
|
||||
error_code ec;
|
||||
JsonExpression expression = jsonpath::make_expression<JsonType>(path, ec);
|
||||
|
@ -1587,8 +1587,8 @@ void JsonFamily::ArrLen(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::ObjLen(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
|
||||
error_code ec;
|
||||
JsonExpression expression = jsonpath::make_expression<JsonType>(path, ec);
|
||||
|
@ -1614,8 +1614,8 @@ void JsonFamily::ObjLen(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::StrLen(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view path = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view path = ArgS(args, 1);
|
||||
|
||||
error_code ec;
|
||||
JsonExpression expression = jsonpath::make_expression<JsonType>(path, ec);
|
||||
|
@ -1641,12 +1641,12 @@ void JsonFamily::StrLen(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void JsonFamily::Get(CmdArgList args, ConnectionContext* cntx) {
|
||||
DCHECK_GE(args.size(), 2U);
|
||||
string_view key = ArgS(args, 1);
|
||||
DCHECK_GE(args.size(), 1U);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
vector<pair<string_view, JsonExpression>> expressions;
|
||||
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
string_view path = ArgS(args, i);
|
||||
error_code ec;
|
||||
JsonExpression expr = jsonpath::make_expression<JsonType>(path, ec);
|
||||
|
|
|
@ -855,6 +855,15 @@ TEST_F(JsonFamilyTest, ArrIndex) {
|
|||
resp = Run({"JSON.ARRINDEX", "json", "$..a", R"("b")"});
|
||||
ASSERT_EQ(RespExpr::ARRAY, resp.type);
|
||||
EXPECT_THAT(resp.GetVec(), ElementsAre(IntArg(1), ArgType(RespExpr::NIL)));
|
||||
|
||||
resp = Run(
|
||||
{"JSON.SET", "json", ".", R"({"key" : ["Alice", "Bob", "Carol", "David", "Eve", "Frank"]})"});
|
||||
ASSERT_EQ(resp, "OK");
|
||||
resp = Run({"JSON.ARRINDEX", "json", "$.key", R"("Bob")"});
|
||||
EXPECT_THAT(resp, IntArg(1));
|
||||
|
||||
resp = Run({"JSON.ARRINDEX", "json", "$.key", R"("Bob")", "1", "2"});
|
||||
EXPECT_THAT(resp, IntArg(1));
|
||||
}
|
||||
|
||||
TEST_F(JsonFamilyTest, MGet) {
|
||||
|
|
|
@ -882,16 +882,16 @@ void MoveGeneric(ConnectionContext* cntx, string_view src, string_view dest, Lis
|
|||
}
|
||||
|
||||
void RPopLPush(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view src = ArgS(args, 1);
|
||||
string_view dest = ArgS(args, 2);
|
||||
string_view src = ArgS(args, 0);
|
||||
string_view dest = ArgS(args, 1);
|
||||
|
||||
MoveGeneric(cntx, src, dest, ListDir::RIGHT, ListDir::LEFT);
|
||||
}
|
||||
|
||||
void BRPopLPush(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view src = ArgS(args, 1);
|
||||
string_view dest = ArgS(args, 2);
|
||||
string_view timeout_str = ArgS(args, 3);
|
||||
string_view src = ArgS(args, 0);
|
||||
string_view dest = ArgS(args, 1);
|
||||
string_view timeout_str = ArgS(args, 2);
|
||||
|
||||
float timeout;
|
||||
if (!absl::SimpleAtof(timeout_str, &timeout)) {
|
||||
|
@ -921,9 +921,9 @@ void BRPopLPush(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void BLMove(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view src = ArgS(args, 1);
|
||||
string_view dest = ArgS(args, 2);
|
||||
string_view timeout_str = ArgS(args, 5);
|
||||
string_view src = ArgS(args, 0);
|
||||
string_view dest = ArgS(args, 1);
|
||||
string_view timeout_str = ArgS(args, 4);
|
||||
|
||||
float timeout;
|
||||
if (!absl::SimpleAtof(timeout_str, &timeout)) {
|
||||
|
@ -934,11 +934,11 @@ void BLMove(CmdArgList args, ConnectionContext* cntx) {
|
|||
return (*cntx)->SendError("timeout is negative");
|
||||
}
|
||||
|
||||
ToUpper(&args[2]);
|
||||
ToUpper(&args[3]);
|
||||
ToUpper(&args[4]);
|
||||
|
||||
optional<ListDir> src_dir = ParseDir(ArgS(args, 3));
|
||||
optional<ListDir> dest_dir = ParseDir(ArgS(args, 4));
|
||||
optional<ListDir> src_dir = ParseDir(ArgS(args, 2));
|
||||
optional<ListDir> dest_dir = ParseDir(ArgS(args, 3));
|
||||
if (!src_dir || !dest_dir) {
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
|
@ -1075,7 +1075,7 @@ void ListFamily::RPop(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ListFamily::LLen(CmdArgList args, ConnectionContext* cntx) {
|
||||
auto key = ArgS(args, 1);
|
||||
auto key = ArgS(args, 0);
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) { return OpLen(t->GetOpArgs(shard), key); };
|
||||
OpResult<uint32_t> result = cntx->transaction->ScheduleSingleHopT(std::move(cb));
|
||||
if (result) {
|
||||
|
@ -1088,15 +1088,15 @@ void ListFamily::LLen(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ListFamily::LPos(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view elem = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view elem = ArgS(args, 1);
|
||||
|
||||
int rank = 1;
|
||||
uint32_t count = 1;
|
||||
uint32_t max_len = 0;
|
||||
bool skip_count = true;
|
||||
|
||||
for (size_t i = 3; i < args.size(); i++) {
|
||||
for (size_t i = 2; i < args.size(); i++) {
|
||||
ToUpper(&args[i]);
|
||||
const auto& arg_v = ArgS(args, i);
|
||||
if (arg_v == "RANK") {
|
||||
|
@ -1146,8 +1146,8 @@ void ListFamily::LPos(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ListFamily::LIndex(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view index_str = ArgS(args, 2);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
std::string_view index_str = ArgS(args, 1);
|
||||
int32_t index;
|
||||
if (!absl::SimpleAtoi(index_str, &index)) {
|
||||
(*cntx)->SendError(kInvalidIntErr);
|
||||
|
@ -1170,10 +1170,10 @@ void ListFamily::LIndex(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
/* LINSERT <key> (BEFORE|AFTER) <pivot> <element> */
|
||||
void ListFamily::LInsert(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view param = ArgS(args, 2);
|
||||
string_view pivot = ArgS(args, 3);
|
||||
string_view elem = ArgS(args, 4);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view param = ArgS(args, 1);
|
||||
string_view pivot = ArgS(args, 2);
|
||||
string_view elem = ArgS(args, 3);
|
||||
int where;
|
||||
|
||||
ToUpper(&args[2]);
|
||||
|
@ -1198,9 +1198,9 @@ void ListFamily::LInsert(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ListFamily::LTrim(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view s_str = ArgS(args, 2);
|
||||
string_view e_str = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view s_str = ArgS(args, 1);
|
||||
string_view e_str = ArgS(args, 2);
|
||||
int32_t start, end;
|
||||
|
||||
if (!absl::SimpleAtoi(s_str, &start) || !absl::SimpleAtoi(e_str, &end)) {
|
||||
|
@ -1216,9 +1216,9 @@ void ListFamily::LTrim(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ListFamily::LRange(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view s_str = ArgS(args, 2);
|
||||
std::string_view e_str = ArgS(args, 3);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
std::string_view s_str = ArgS(args, 1);
|
||||
std::string_view e_str = ArgS(args, 2);
|
||||
int32_t start, end;
|
||||
|
||||
if (!absl::SimpleAtoi(s_str, &start) || !absl::SimpleAtoi(e_str, &end)) {
|
||||
|
@ -1240,9 +1240,9 @@ void ListFamily::LRange(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
// lrem key 5 foo, will remove foo elements from the list if exists at most 5 times.
|
||||
void ListFamily::LRem(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view index_str = ArgS(args, 2);
|
||||
std::string_view elem = ArgS(args, 3);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
std::string_view index_str = ArgS(args, 1);
|
||||
std::string_view elem = ArgS(args, 2);
|
||||
int32_t count;
|
||||
|
||||
if (!absl::SimpleAtoi(index_str, &count)) {
|
||||
|
@ -1262,9 +1262,9 @@ void ListFamily::LRem(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ListFamily::LSet(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
std::string_view index_str = ArgS(args, 2);
|
||||
std::string_view elem = ArgS(args, 3);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
std::string_view index_str = ArgS(args, 1);
|
||||
std::string_view elem = ArgS(args, 2);
|
||||
int32_t count;
|
||||
|
||||
if (!absl::SimpleAtoi(index_str, &count)) {
|
||||
|
@ -1292,13 +1292,13 @@ void ListFamily::BRPop(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ListFamily::LMove(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view src = ArgS(args, 1);
|
||||
std::string_view dest = ArgS(args, 2);
|
||||
std::string_view src_dir_str = ArgS(args, 3);
|
||||
std::string_view dest_dir_str = ArgS(args, 4);
|
||||
std::string_view src = ArgS(args, 0);
|
||||
std::string_view dest = ArgS(args, 1);
|
||||
std::string_view src_dir_str = ArgS(args, 2);
|
||||
std::string_view dest_dir_str = ArgS(args, 3);
|
||||
|
||||
ToUpper(&args[2]);
|
||||
ToUpper(&args[3]);
|
||||
ToUpper(&args[4]);
|
||||
|
||||
optional<ListDir> src_dir = ParseDir(src_dir_str);
|
||||
optional<ListDir> dest_dir = ParseDir(dest_dir_str);
|
||||
|
@ -1310,7 +1310,7 @@ void ListFamily::LMove(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ListFamily::BPopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cntx) {
|
||||
DCHECK_GE(args.size(), 3u);
|
||||
DCHECK_GE(args.size(), 2u);
|
||||
|
||||
float timeout;
|
||||
auto timeout_str = ArgS(args, args.size() - 1);
|
||||
|
@ -1351,10 +1351,10 @@ void ListFamily::BPopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cn
|
|||
|
||||
void ListFamily::PushGeneric(ListDir dir, bool skip_notexists, CmdArgList args,
|
||||
ConnectionContext* cntx) {
|
||||
std::string_view key = ArgS(args, 1);
|
||||
vector<std::string_view> vals(args.size() - 2);
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
vals[i - 2] = ArgS(args, i);
|
||||
std::string_view key = ArgS(args, 0);
|
||||
vector<std::string_view> vals(args.size() - 1);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
vals[i - 1] = ArgS(args, i);
|
||||
}
|
||||
absl::Span<std::string_view> span{vals.data(), vals.size()};
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
|
@ -1370,17 +1370,16 @@ void ListFamily::PushGeneric(ListDir dir, bool skip_notexists, CmdArgList args,
|
|||
}
|
||||
|
||||
void ListFamily::PopGeneric(ListDir dir, CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
int32_t count = 1;
|
||||
bool return_arr = false;
|
||||
|
||||
if (args.size() > 2) {
|
||||
if (args.size() > 3) {
|
||||
ToLower(&args[0]);
|
||||
return (*cntx)->SendError(WrongNumArgsError(ArgS(args, 0)));
|
||||
if (args.size() > 1) {
|
||||
if (args.size() > 2) {
|
||||
return (*cntx)->SendError(WrongNumArgsError(cntx->cid->name()));
|
||||
}
|
||||
|
||||
string_view count_s = ArgS(args, 2);
|
||||
string_view count_s = ArgS(args, 1);
|
||||
if (!absl::SimpleAtoi(count_s, &count)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ bool IsSHA(string_view str) {
|
|||
}
|
||||
|
||||
bool EvalValidator(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view num_keys_str = ArgS(args, 2);
|
||||
string_view num_keys_str = ArgS(args, 1);
|
||||
int32_t num_keys;
|
||||
|
||||
if (!absl::SimpleAtoi(num_keys_str, &num_keys) || num_keys < 0) {
|
||||
|
@ -406,7 +406,7 @@ bool EvalValidator(CmdArgList args, ConnectionContext* cntx) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (unsigned(num_keys) > args.size() - 3) {
|
||||
if (unsigned(num_keys) > args.size() - 2) {
|
||||
(*cntx)->SendError("Number of keys can't be greater than number of args", kSyntaxErrType);
|
||||
return false;
|
||||
}
|
||||
|
@ -585,7 +585,7 @@ OpStatus CheckKeysDeclared(const ConnectionState::ScriptInfo& eval_info, const C
|
|||
}
|
||||
}
|
||||
|
||||
if (unsigned i = key_index.bonus; i && !eval_info.keys.contains(ArgS(args, i)))
|
||||
if (key_index.bonus && !eval_info.keys.contains(ArgS(args, *key_index.bonus)))
|
||||
return OpStatus::KEY_NOTFOUND;
|
||||
|
||||
return OpStatus::OK;
|
||||
|
@ -668,7 +668,7 @@ void Service::DispatchCommand(CmdArgList args, facade::ConnectionContext* cntx)
|
|||
}
|
||||
|
||||
// Validate more complicated cases with custom validators.
|
||||
if (!cid->Validate(args, dfly_cntx)) {
|
||||
if (!cid->Validate(args.subspan(1), dfly_cntx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -699,7 +699,7 @@ void Service::DispatchCommand(CmdArgList args, facade::ConnectionContext* cntx)
|
|||
return (*cntx)->SendError(error);
|
||||
}
|
||||
// TODO: protect against aggregating huge transactions.
|
||||
StoredCmd stored_cmd{cid, args};
|
||||
StoredCmd stored_cmd{cid, args.subspan(1)};
|
||||
dfly_cntx->conn_state.exec_info.body.push_back(std::move(stored_cmd));
|
||||
|
||||
return (*cntx)->SendSimpleString("QUEUED");
|
||||
|
@ -714,8 +714,8 @@ void Service::DispatchCommand(CmdArgList args, facade::ConnectionContext* cntx)
|
|||
if (under_script) {
|
||||
DCHECK(dfly_cntx->transaction);
|
||||
if (cid->IsTransactional()) {
|
||||
OpStatus status =
|
||||
CheckKeysDeclared(*dfly_cntx->conn_state.script_info, cid, args, dfly_cntx->transaction);
|
||||
OpStatus status = CheckKeysDeclared(*dfly_cntx->conn_state.script_info, cid, args.subspan(1),
|
||||
dfly_cntx->transaction);
|
||||
|
||||
if (status == OpStatus::KEY_NOTFOUND)
|
||||
return (*cntx)->SendError("script tried accessing undeclared key");
|
||||
|
@ -724,7 +724,7 @@ void Service::DispatchCommand(CmdArgList args, facade::ConnectionContext* cntx)
|
|||
return (*cntx)->SendError(status);
|
||||
|
||||
dfly_cntx->transaction->MultiSwitchCmd(cid);
|
||||
status = dfly_cntx->transaction->InitByArgs(dfly_cntx->conn_state.db_index, args);
|
||||
status = dfly_cntx->transaction->InitByArgs(dfly_cntx->conn_state.db_index, args.subspan(1));
|
||||
|
||||
if (status != OpStatus::OK)
|
||||
return (*cntx)->SendError(status);
|
||||
|
@ -736,7 +736,7 @@ void Service::DispatchCommand(CmdArgList args, facade::ConnectionContext* cntx)
|
|||
dist_trans.reset(new Transaction{cid, etl.thread_index()});
|
||||
|
||||
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);
|
||||
if (auto st = dist_trans->InitByArgs(dfly_cntx->conn_state.db_index, args.subspan(1));
|
||||
st != OpStatus::OK)
|
||||
return (*cntx)->SendError(st);
|
||||
}
|
||||
|
@ -754,7 +754,7 @@ void Service::DispatchCommand(CmdArgList args, facade::ConnectionContext* cntx)
|
|||
// itself. EXEC does not use DispatchCommand for dispatching.
|
||||
bool collect_stats =
|
||||
dfly_cntx->transaction && (!dfly_cntx->transaction->IsMulti() || under_script);
|
||||
if (!InvokeCmd(args, cid, dfly_cntx, collect_stats)) {
|
||||
if (!InvokeCmd(args.subspan(1), cid, dfly_cntx, collect_stats)) {
|
||||
dfly_cntx->reply_builder()->SendError("Internal Error");
|
||||
dfly_cntx->reply_builder()->CloseConnection();
|
||||
}
|
||||
|
@ -977,7 +977,7 @@ void Service::Watch(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
// Duplicate keys are stored to keep correct count.
|
||||
exec_info.watched_existed += keys_existed.load(memory_order_relaxed);
|
||||
for (size_t i = 1; i < args.size(); i++) {
|
||||
for (size_t i = 0; i < args.size(); i++) {
|
||||
exec_info.watched_keys.emplace_back(cntx->db_index(), ArgS(args, i));
|
||||
}
|
||||
|
||||
|
@ -1004,9 +1004,9 @@ void Service::CallFromScript(CmdArgList args, ObjectExplorer* reply, ConnectionC
|
|||
void Service::Eval(CmdArgList args, ConnectionContext* cntx) {
|
||||
uint32_t num_keys;
|
||||
|
||||
CHECK(absl::SimpleAtoi(ArgS(args, 2), &num_keys)); // we already validated this
|
||||
CHECK(absl::SimpleAtoi(ArgS(args, 1), &num_keys)); // we already validated this
|
||||
|
||||
string_view body = ArgS(args, 1);
|
||||
string_view body = ArgS(args, 0);
|
||||
// body = absl::StripAsciiWhitespace(body);
|
||||
|
||||
if (body.empty()) {
|
||||
|
@ -1025,8 +1025,8 @@ void Service::Eval(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
EvalArgs eval_args;
|
||||
eval_args.sha = sha;
|
||||
eval_args.keys = args.subspan(3, num_keys);
|
||||
eval_args.args = args.subspan(3 + num_keys);
|
||||
eval_args.keys = args.subspan(2, num_keys);
|
||||
eval_args.args = args.subspan(2 + num_keys);
|
||||
|
||||
uint64_t start = absl::GetCurrentTimeNanos();
|
||||
EvalInternal(eval_args, interpreter, cntx);
|
||||
|
@ -1036,22 +1036,22 @@ void Service::Eval(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void Service::EvalSha(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view num_keys_str = ArgS(args, 2);
|
||||
string_view num_keys_str = ArgS(args, 1);
|
||||
uint32_t num_keys;
|
||||
|
||||
CHECK(absl::SimpleAtoi(num_keys_str, &num_keys));
|
||||
|
||||
ToLower(&args[1]);
|
||||
ToLower(&args[0]);
|
||||
|
||||
string_view sha = ArgS(args, 1);
|
||||
string_view sha = ArgS(args, 0);
|
||||
ServerState* ss = ServerState::tlocal();
|
||||
auto interpreter = ss->BorrowInterpreter();
|
||||
absl::Cleanup clean = [ss, interpreter]() { ss->ReturnInterpreter(interpreter); };
|
||||
|
||||
EvalArgs ev_args;
|
||||
ev_args.sha = sha;
|
||||
ev_args.keys = args.subspan(3, num_keys);
|
||||
ev_args.args = args.subspan(3 + num_keys);
|
||||
ev_args.keys = args.subspan(2, num_keys);
|
||||
ev_args.args = args.subspan(2 + num_keys);
|
||||
|
||||
uint64_t start = absl::GetCurrentTimeNanos();
|
||||
EvalInternal(ev_args, interpreter, cntx);
|
||||
|
@ -1201,10 +1201,9 @@ bool CheckWatchedKeyExpiry(ConnectionContext* cntx, const CommandRegistry& regis
|
|||
static char EXISTS[] = "EXISTS";
|
||||
auto& exec_info = cntx->conn_state.exec_info;
|
||||
|
||||
CmdArgVec str_list(exec_info.watched_keys.size() + 1);
|
||||
str_list[0] = MutableSlice{EXISTS, strlen(EXISTS)};
|
||||
for (size_t i = 1; i < str_list.size(); i++) {
|
||||
auto& [db, s] = exec_info.watched_keys[i - 1];
|
||||
CmdArgVec str_list(exec_info.watched_keys.size());
|
||||
for (size_t i = 0; i < str_list.size(); i++) {
|
||||
auto& [db, s] = exec_info.watched_keys[i];
|
||||
str_list[i] = MutableSlice{s.data(), s.size()};
|
||||
}
|
||||
|
||||
|
@ -1218,8 +1217,7 @@ bool CheckWatchedKeyExpiry(ConnectionContext* cntx, const CommandRegistry& regis
|
|||
};
|
||||
|
||||
cntx->transaction->MultiSwitchCmd(registry.Find(EXISTS));
|
||||
cntx->transaction->InitByArgs(cntx->conn_state.db_index,
|
||||
CmdArgList{str_list.data(), str_list.size()});
|
||||
cntx->transaction->InitByArgs(cntx->conn_state.db_index, CmdArgList{str_list});
|
||||
OpStatus status = cntx->transaction->ScheduleSingleHop(std::move(cb));
|
||||
CHECK_EQ(OpStatus::OK, status);
|
||||
|
||||
|
@ -1259,7 +1257,7 @@ template <typename F> void IterateAllKeys(ConnectionState::ExecInfo* exec_info,
|
|||
f(args[i]);
|
||||
|
||||
if (key_index.bonus)
|
||||
f(args[key_index.bonus]);
|
||||
f(args[*key_index.bonus]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1390,7 +1388,7 @@ void Service::Exec(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void Service::Publish(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view channel = ArgS(args, 1);
|
||||
string_view channel = ArgS(args, 0);
|
||||
|
||||
auto* cs = ServerState::tlocal()->channel_store();
|
||||
vector<ChannelStore::Subscriber> subscribers = cs->FetchSubscribers(channel);
|
||||
|
@ -1398,7 +1396,7 @@ void Service::Publish(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
if (!subscribers.empty()) {
|
||||
auto subscribers_ptr = make_shared<decltype(subscribers)>(move(subscribers));
|
||||
auto msg_ptr = make_shared<string>(ArgS(args, 2));
|
||||
auto msg_ptr = make_shared<string>(ArgS(args, 1));
|
||||
auto channel_ptr = make_shared<string>(channel);
|
||||
|
||||
auto cb = [subscribers_ptr, msg_ptr, channel_ptr](unsigned idx, util::ProactorBase*) {
|
||||
|
@ -1420,14 +1418,10 @@ void Service::Publish(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void Service::Subscribe(CmdArgList args, ConnectionContext* cntx) {
|
||||
args.remove_prefix(1);
|
||||
|
||||
cntx->ChangeSubscription(true /*add*/, true /* reply*/, std::move(args));
|
||||
}
|
||||
|
||||
void Service::Unsubscribe(CmdArgList args, ConnectionContext* cntx) {
|
||||
args.remove_prefix(1);
|
||||
|
||||
if (args.size() == 0) {
|
||||
cntx->UnsubscribeAll(true);
|
||||
} else {
|
||||
|
@ -1436,13 +1430,10 @@ void Service::Unsubscribe(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void Service::PSubscribe(CmdArgList args, ConnectionContext* cntx) {
|
||||
args.remove_prefix(1);
|
||||
cntx->ChangePSubscription(true, true, args);
|
||||
}
|
||||
|
||||
void Service::PUnsubscribe(CmdArgList args, ConnectionContext* cntx) {
|
||||
args.remove_prefix(1);
|
||||
|
||||
if (args.size() == 0) {
|
||||
cntx->PUnsubscribeAll(true);
|
||||
} else {
|
||||
|
@ -1453,8 +1444,8 @@ void Service::PUnsubscribe(CmdArgList args, ConnectionContext* cntx) {
|
|||
// Not a real implementation. Serves as a decorator to accept some function commands
|
||||
// for testing.
|
||||
void Service::Function(CmdArgList args, ConnectionContext* cntx) {
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
|
||||
if (sub_cmd == "FLUSH") {
|
||||
return (*cntx)->SendOk();
|
||||
|
@ -1483,13 +1474,13 @@ void Service::Monitor(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void Service::Pubsub(CmdArgList args, ConnectionContext* cntx) {
|
||||
if (args.size() < 2) {
|
||||
(*cntx)->SendError(WrongNumArgsError(ArgS(args, 0)));
|
||||
if (args.size() < 1) {
|
||||
(*cntx)->SendError(WrongNumArgsError(cntx->cid->name()));
|
||||
return;
|
||||
}
|
||||
|
||||
ToUpper(&args[1]);
|
||||
string_view subcmd = ArgS(args, 1);
|
||||
ToUpper(&args[0]);
|
||||
string_view subcmd = ArgS(args, 0);
|
||||
|
||||
if (subcmd == "HELP") {
|
||||
string_view help_arr[] = {
|
||||
|
@ -1507,8 +1498,8 @@ void Service::Pubsub(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
if (subcmd == "CHANNELS") {
|
||||
string_view pattern;
|
||||
if (args.size() > 2) {
|
||||
pattern = ArgS(args, 2);
|
||||
if (args.size() > 1) {
|
||||
pattern = ArgS(args, 1);
|
||||
}
|
||||
|
||||
PubsubChannels(pattern, cntx);
|
||||
|
|
|
@ -73,7 +73,7 @@ MemoryCmd::MemoryCmd(ServerFamily* owner, ConnectionContext* cntx) : cntx_(cntx)
|
|||
}
|
||||
|
||||
void MemoryCmd::Run(CmdArgList args) {
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
|
||||
if (sub_cmd == "HELP") {
|
||||
string_view help_arr[] = {
|
||||
|
|
|
@ -17,7 +17,7 @@ template <typename F> void IterateKeys(CmdArgList args, KeyIndex keys, F&& f) {
|
|||
f(args[i]);
|
||||
|
||||
if (keys.bonus)
|
||||
f(args[keys.bonus]);
|
||||
f(args[*keys.bonus]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -275,8 +275,8 @@ void ExtendFilenameWithShard(absl::Time now, int shard, fs::path* filename) {
|
|||
}
|
||||
|
||||
void SlowLog(CmdArgList args, ConnectionContext* cntx) {
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
|
||||
if (sub_cmd == "LEN") {
|
||||
return (*cntx)->SendLong(0);
|
||||
|
@ -1106,7 +1106,7 @@ void ServerFamily::FlushAll(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ServerFamily::Auth(CmdArgList args, ConnectionContext* cntx) {
|
||||
if (args.size() > 3) {
|
||||
if (args.size() > 2) {
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
|
||||
|
@ -1120,7 +1120,7 @@ void ServerFamily::Auth(CmdArgList args, ConnectionContext* cntx) {
|
|||
"default user. Are you sure your configuration is correct?");
|
||||
}
|
||||
|
||||
string_view pass = ArgS(args, 1);
|
||||
string_view pass = ArgS(args, 0);
|
||||
if (pass == GetPassword()) {
|
||||
cntx->authenticated = true;
|
||||
(*cntx)->SendOk();
|
||||
|
@ -1130,11 +1130,11 @@ void ServerFamily::Auth(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ServerFamily::Client(CmdArgList args, ConnectionContext* cntx) {
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
|
||||
if (sub_cmd == "SETNAME" && args.size() == 3) {
|
||||
cntx->owner()->SetName(ArgS(args, 2));
|
||||
if (sub_cmd == "SETNAME" && args.size() == 2) {
|
||||
cntx->owner()->SetName(ArgS(args, 1));
|
||||
return (*cntx)->SendOk();
|
||||
}
|
||||
|
||||
|
@ -1184,8 +1184,8 @@ void ServerFamily::Cluster(CmdArgList args, ConnectionContext* cntx) {
|
|||
constexpr unsigned int kNoReplicaInfoSize = 3;
|
||||
constexpr unsigned int kWithReplicaInfoSize = 4;
|
||||
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
|
||||
if (!is_emulated_cluster_) {
|
||||
return (*cntx)->SendError("CLUSTER commands requires --cluster_mode=emulated");
|
||||
|
@ -1308,13 +1308,13 @@ void ServerFamily::Cluster(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ServerFamily::Config(CmdArgList args, ConnectionContext* cntx) {
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
|
||||
if (sub_cmd == "SET") {
|
||||
return (*cntx)->SendOk();
|
||||
} else if (sub_cmd == "GET" && args.size() == 3) {
|
||||
string_view param = ArgS(args, 2);
|
||||
} else if (sub_cmd == "GET" && args.size() == 2) {
|
||||
string_view param = ArgS(args, 1);
|
||||
string_view res[2] = {param, "tbd"};
|
||||
|
||||
return (*cntx)->SendStringArr(res, RedisReplyBuilder::MAP);
|
||||
|
@ -1333,7 +1333,7 @@ void ServerFamily::Config(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ServerFamily::Debug(CmdArgList args, ConnectionContext* cntx) {
|
||||
ToUpper(&args[1]);
|
||||
ToUpper(&args[0]);
|
||||
|
||||
DebugCmd dbg_cmd{this, cntx};
|
||||
|
||||
|
@ -1341,7 +1341,7 @@ void ServerFamily::Debug(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ServerFamily::Memory(CmdArgList args, ConnectionContext* cntx) {
|
||||
ToUpper(&args[1]);
|
||||
ToUpper(&args[0]);
|
||||
|
||||
MemoryCmd mem_cmd{this, cntx};
|
||||
|
||||
|
@ -1355,9 +1355,9 @@ void ServerFamily::Save(CmdArgList args, ConnectionContext* cntx) {
|
|||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
|
||||
if (args.size() == 2) {
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
if (args.size() == 1) {
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
if (sub_cmd == "DF") {
|
||||
new_version = true;
|
||||
} else if (sub_cmd == "RDB") {
|
||||
|
@ -1424,15 +1424,15 @@ Metrics ServerFamily::GetMetrics() const {
|
|||
}
|
||||
|
||||
void ServerFamily::Info(CmdArgList args, ConnectionContext* cntx) {
|
||||
if (args.size() > 2) {
|
||||
if (args.size() > 1) {
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
|
||||
string_view section;
|
||||
|
||||
if (args.size() == 2) {
|
||||
ToUpper(&args[1]);
|
||||
section = ArgS(args, 1);
|
||||
if (args.size() == 1) {
|
||||
ToUpper(&args[0]);
|
||||
section = ArgS(args, 0);
|
||||
}
|
||||
|
||||
string info;
|
||||
|
@ -1691,12 +1691,12 @@ void ServerFamily::Hello(CmdArgList args, ConnectionContext* cntx) {
|
|||
// If no arguments are provided default to RESP2.
|
||||
// AUTH and SETNAME options are not supported.
|
||||
bool is_resp3 = false;
|
||||
if (args.size() > 1) {
|
||||
string_view proto_version = ArgS(args, 1);
|
||||
if (args.size() > 0) {
|
||||
string_view proto_version = ArgS(args, 0);
|
||||
is_resp3 = proto_version == "3";
|
||||
bool valid_proto_version = proto_version == "2" || is_resp3;
|
||||
if (!valid_proto_version || args.size() > 2) {
|
||||
(*cntx)->SendError(UnknownCmd("HELLO", args.subspan(1)));
|
||||
if (!valid_proto_version || args.size() > 1) {
|
||||
(*cntx)->SendError(UnknownCmd("HELLO", args));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1764,8 +1764,8 @@ std::string ServerFamily::BuildClusterNodeReply(ConnectionContext* cntx) const {
|
|||
}
|
||||
|
||||
void ServerFamily::ReplicaOf(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view host = ArgS(args, 1);
|
||||
std::string_view port_s = ArgS(args, 2);
|
||||
std::string_view host = ArgS(args, 0);
|
||||
std::string_view port_s = ArgS(args, 1);
|
||||
auto& pool = service_.proactor_pool();
|
||||
|
||||
LOG(INFO) << "Replicating " << host << ":" << port_s;
|
||||
|
@ -1838,16 +1838,16 @@ void ServerFamily::ReplicaOf(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ServerFamily::ReplConf(CmdArgList args, ConnectionContext* cntx) {
|
||||
if (args.size() % 2 == 0)
|
||||
if (args.size() % 2 == 1)
|
||||
goto err;
|
||||
for (unsigned i = 1; i < args.size(); i += 2) {
|
||||
for (unsigned i = 0; i < args.size(); i += 2) {
|
||||
DCHECK_LT(i + 1, args.size());
|
||||
ToUpper(&args[i]);
|
||||
|
||||
std::string_view cmd = ArgS(args, i);
|
||||
std::string_view arg = ArgS(args, i + 1);
|
||||
if (cmd == "CAPA") {
|
||||
if (arg == "dragonfly" && args.size() == 3 && i == 1) {
|
||||
if (arg == "dragonfly" && args.size() == 2 && i == 0) {
|
||||
uint32_t sid = dfly_cmd_->CreateSyncSession(cntx);
|
||||
cntx->owner()->SetName(absl::StrCat("repl_ctrl_", sid));
|
||||
|
||||
|
@ -1922,7 +1922,6 @@ void ServerFamily::Role(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ServerFamily::Script(CmdArgList args, ConnectionContext* cntx) {
|
||||
args.remove_prefix(1);
|
||||
ToUpper(&args.front());
|
||||
|
||||
script_mgr_->Run(std::move(args), cntx);
|
||||
|
@ -1953,8 +1952,8 @@ void ServerFamily::LastSave(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ServerFamily::Latency(CmdArgList args, ConnectionContext* cntx) {
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 01);
|
||||
|
||||
if (sub_cmd == "LATEST") {
|
||||
return (*cntx)->SendEmptyArray();
|
||||
|
|
|
@ -1042,10 +1042,10 @@ OpResult<StringVec> OpScan(const OpArgs& op_args, string_view key, uint64_t* cur
|
|||
}
|
||||
|
||||
void SAdd(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
vector<string_view> vals(args.size() - 2);
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
vals[i - 2] = ArgS(args, i);
|
||||
string_view key = ArgS(args, 0);
|
||||
vector<string_view> vals(args.size() - 1);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
vals[i - 1] = ArgS(args, i);
|
||||
}
|
||||
ArgSlice arg_slice{vals.data(), vals.size()};
|
||||
|
||||
|
@ -1062,8 +1062,8 @@ void SAdd(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void SIsMember(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view val = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view val = ArgS(args, 1);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
OpResult<PrimeIterator> find_res = shard->db_slice().Find(t->GetDbContext(), key, OBJ_SET);
|
||||
|
@ -1086,11 +1086,11 @@ void SIsMember(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void SMIsMember(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
vector<string_view> vals(args.size() - 2);
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
vals[i - 2] = ArgS(args, i);
|
||||
vector<string_view> vals(args.size() - 1);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
vals[i - 1] = ArgS(args, i);
|
||||
}
|
||||
|
||||
StringVec memberships;
|
||||
|
@ -1117,9 +1117,9 @@ void SMIsMember(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void SMove(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view src = ArgS(args, 1);
|
||||
string_view dest = ArgS(args, 2);
|
||||
string_view member = ArgS(args, 3);
|
||||
string_view src = ArgS(args, 0);
|
||||
string_view dest = ArgS(args, 1);
|
||||
string_view member = ArgS(args, 2);
|
||||
|
||||
Mover mover{src, dest, member, true};
|
||||
cntx->transaction->Schedule();
|
||||
|
@ -1136,10 +1136,10 @@ void SMove(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void SRem(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
vector<string_view> vals(args.size() - 2);
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
vals[i - 2] = ArgS(args, i);
|
||||
string_view key = ArgS(args, 0);
|
||||
vector<string_view> vals(args.size() - 1);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
vals[i - 1] = ArgS(args, i);
|
||||
}
|
||||
ArgSlice span{vals.data(), vals.size()};
|
||||
|
||||
|
@ -1159,7 +1159,7 @@ void SRem(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void SCard(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<uint32_t> {
|
||||
OpResult<PrimeIterator> find_res = shard->db_slice().Find(t->GetDbContext(), key, OBJ_SET);
|
||||
|
@ -1183,10 +1183,10 @@ void SCard(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void SPop(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
unsigned count = 1;
|
||||
if (args.size() > 2) {
|
||||
string_view arg = ArgS(args, 2);
|
||||
if (args.size() > 1) {
|
||||
string_view arg = ArgS(args, 1);
|
||||
if (!absl::SimpleAtoi(arg, &count)) {
|
||||
(*cntx)->SendError(kInvalidIntErr);
|
||||
return;
|
||||
|
@ -1199,7 +1199,7 @@ void SPop(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
OpResult<StringVec> result = cntx->transaction->ScheduleSingleHopT(std::move(cb));
|
||||
if (result || result.status() == OpStatus::KEY_NOTFOUND) {
|
||||
if (args.size() == 2) { // SPOP key
|
||||
if (args.size() == 1) { // SPOP key
|
||||
if (result.status() == OpStatus::KEY_NOTFOUND) {
|
||||
(*cntx)->SendNull();
|
||||
} else {
|
||||
|
@ -1217,7 +1217,7 @@ void SPop(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void SDiff(CmdArgList args, ConnectionContext* cntx) {
|
||||
ResultStringVec result_set(shard_set->size(), OpStatus::SKIPPED);
|
||||
string_view src_key = ArgS(args, 1);
|
||||
string_view src_key = ArgS(args, 0);
|
||||
ShardId src_shard = Shard(src_key, result_set.size());
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
|
@ -1248,9 +1248,9 @@ void SDiff(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void SDiffStore(CmdArgList args, ConnectionContext* cntx) {
|
||||
ResultStringVec result_set(shard_set->size(), OpStatus::SKIPPED);
|
||||
string_view dest_key = ArgS(args, 1);
|
||||
string_view dest_key = ArgS(args, 0);
|
||||
ShardId dest_shard = Shard(dest_key, result_set.size());
|
||||
string_view src_key = ArgS(args, 2);
|
||||
string_view src_key = ArgS(args, 1);
|
||||
ShardId src_shard = Shard(src_key, result_set.size());
|
||||
|
||||
VLOG(1) << "SDiffStore " << src_key << " " << src_shard;
|
||||
|
@ -1341,7 +1341,7 @@ void SInter(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void SInterStore(CmdArgList args, ConnectionContext* cntx) {
|
||||
ResultStringVec result_set(shard_set->size(), OpStatus::SKIPPED);
|
||||
string_view dest_key = ArgS(args, 1);
|
||||
string_view dest_key = ArgS(args, 0);
|
||||
ShardId dest_shard = Shard(dest_key, result_set.size());
|
||||
atomic_uint32_t inter_shard_cnt{0};
|
||||
|
||||
|
@ -1404,7 +1404,7 @@ void SUnion(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
void SUnionStore(CmdArgList args, ConnectionContext* cntx) {
|
||||
ResultStringVec result_set(shard_set->size(), OpStatus::SKIPPED);
|
||||
string_view dest_key = ArgS(args, 1);
|
||||
string_view dest_key = ArgS(args, 0);
|
||||
ShardId dest_shard = Shard(dest_key, result_set.size());
|
||||
|
||||
auto union_cb = [&](Transaction* t, EngineShard* shard) {
|
||||
|
@ -1444,8 +1444,8 @@ void SUnionStore(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void SScan(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view token = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view token = ArgS(args, 1);
|
||||
|
||||
uint64_t cursor = 0;
|
||||
|
||||
|
@ -1454,12 +1454,12 @@ void SScan(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
// SSCAN key cursor [MATCH pattern] [COUNT count]
|
||||
if (args.size() > 7) {
|
||||
if (args.size() > 6) {
|
||||
DVLOG(1) << "got " << args.size() << " this is more than it should be";
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
|
||||
OpResult<ScanOpts> ops = ScanOpts::TryFrom(args.subspan(3));
|
||||
OpResult<ScanOpts> ops = ScanOpts::TryFrom(args.subspan(2));
|
||||
if (!ops) {
|
||||
DVLOG(1) << "SScan invalid args - return " << ops << " to the user";
|
||||
return (*cntx)->SendError(ops.status());
|
||||
|
@ -1486,8 +1486,8 @@ void SScan(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
// Syntax: saddex key ttl_sec member [member...]
|
||||
void SAddEx(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view ttl_str = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view ttl_str = ArgS(args, 1);
|
||||
uint32_t ttl_sec;
|
||||
constexpr uint32_t kMaxTtl = (1UL << 26);
|
||||
|
||||
|
|
|
@ -566,8 +566,8 @@ void SetId(string_view key, string_view gname, CmdArgList args, ConnectionContex
|
|||
} // namespace
|
||||
|
||||
void StreamFamily::XAdd(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
unsigned id_indx = 2;
|
||||
string_view key = ArgS(args, 0);
|
||||
unsigned id_indx = 1;
|
||||
AddOpts add_opts;
|
||||
|
||||
for (; id_indx < args.size(); ++id_indx) {
|
||||
|
@ -592,7 +592,7 @@ void StreamFamily::XAdd(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
args.remove_prefix(id_indx);
|
||||
if (args.size() < 3 || args.size() % 2 == 0) {
|
||||
if (args.size() < 2 || args.size() % 2 == 0) {
|
||||
return (*cntx)->SendError(WrongNumArgsError("XADD"), kSyntaxErrType);
|
||||
}
|
||||
|
||||
|
@ -622,8 +622,8 @@ void StreamFamily::XAdd(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StreamFamily::XDel(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
args.remove_prefix(2);
|
||||
string_view key = ArgS(args, 0);
|
||||
args.remove_prefix(1);
|
||||
|
||||
absl::InlinedVector<streamID, 8> ids(args.size());
|
||||
|
||||
|
@ -649,8 +649,8 @@ void StreamFamily::XDel(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StreamFamily::XGroup(CmdArgList args, ConnectionContext* cntx) {
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
if (sub_cmd == "HELP") {
|
||||
string_view help_arr[] = {
|
||||
"CREATE <key> <groupname> <id|$> [option]",
|
||||
|
@ -669,27 +669,27 @@ void StreamFamily::XGroup(CmdArgList args, ConnectionContext* cntx) {
|
|||
return (*cntx)->SendSimpleStrArr(help_arr);
|
||||
}
|
||||
|
||||
if (args.size() >= 3) {
|
||||
string_view key = ArgS(args, 2);
|
||||
if (args.size() >= 2) {
|
||||
string_view key = ArgS(args, 1);
|
||||
if (sub_cmd == "CREATE") {
|
||||
args.remove_prefix(3);
|
||||
args.remove_prefix(2);
|
||||
return CreateGroup(std::move(args), key, cntx);
|
||||
}
|
||||
|
||||
if (sub_cmd == "DESTROY" && args.size() == 4) {
|
||||
string_view gname = ArgS(args, 3);
|
||||
if (sub_cmd == "DESTROY" && args.size() == 3) {
|
||||
string_view gname = ArgS(args, 2);
|
||||
return DestroyGroup(key, gname, cntx);
|
||||
}
|
||||
|
||||
if (sub_cmd == "DELCONSUMER" && args.size() == 5) {
|
||||
string_view gname = ArgS(args, 3);
|
||||
string_view cname = ArgS(args, 4);
|
||||
if (sub_cmd == "DELCONSUMER" && args.size() == 4) {
|
||||
string_view gname = ArgS(args, 2);
|
||||
string_view cname = ArgS(args, 3);
|
||||
return DelConsumer(key, gname, cname, cntx);
|
||||
}
|
||||
|
||||
if (sub_cmd == "SETID" && args.size() >= 5) {
|
||||
string_view gname = ArgS(args, 3);
|
||||
args.remove_prefix(4);
|
||||
if (sub_cmd == "SETID" && args.size() >= 4) {
|
||||
string_view gname = ArgS(args, 2);
|
||||
args.remove_prefix(3);
|
||||
return SetId(key, gname, std::move(args), cntx);
|
||||
}
|
||||
}
|
||||
|
@ -698,8 +698,8 @@ void StreamFamily::XGroup(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) {
|
||||
ToUpper(&args[1]);
|
||||
string_view sub_cmd = ArgS(args, 1);
|
||||
ToUpper(&args[0]);
|
||||
string_view sub_cmd = ArgS(args, 0);
|
||||
if (sub_cmd == "HELP") {
|
||||
string_view help_arr[] = {
|
||||
"CONSUMERS <key> <groupname>",
|
||||
|
@ -712,8 +712,8 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) {
|
|||
return (*cntx)->SendSimpleStrArr(help_arr);
|
||||
}
|
||||
|
||||
if (args.size() >= 3) {
|
||||
string_view key = ArgS(args, 2);
|
||||
if (args.size() >= 2) {
|
||||
string_view key = ArgS(args, 1);
|
||||
ShardId sid = Shard(key, shard_set->size());
|
||||
|
||||
if (sub_cmd == "GROUPS") {
|
||||
|
@ -745,7 +745,7 @@ void StreamFamily::XInfo(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StreamFamily::XLen(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) { return OpLen(t->GetOpArgs(shard), key); };
|
||||
|
||||
OpResult<uint32_t> result = cntx->transaction->ScheduleSingleHopT(std::move(cb));
|
||||
|
@ -765,8 +765,8 @@ void StreamFamily::XRevRange(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StreamFamily::XSetId(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view idstr = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view idstr = ArgS(args, 1);
|
||||
|
||||
ParsedStreamId parsed_id;
|
||||
if (!ParseID(idstr, true, 0, &parsed_id)) {
|
||||
|
@ -792,9 +792,9 @@ void StreamFamily::XSetId(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StreamFamily::XRangeGeneric(CmdArgList args, bool is_rev, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view start = ArgS(args, 2);
|
||||
string_view end = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view start = ArgS(args, 1);
|
||||
string_view end = ArgS(args, 2);
|
||||
RangeOpts range_opts;
|
||||
RangeId rs, re;
|
||||
if (!ParseRangeId(start, &rs) || !ParseRangeId(end, &re)) {
|
||||
|
@ -809,13 +809,13 @@ void StreamFamily::XRangeGeneric(CmdArgList args, bool is_rev, ConnectionContext
|
|||
return (*cntx)->SendError("invalid end ID for the interval", kSyntaxErrType);
|
||||
}
|
||||
|
||||
if (args.size() > 4) {
|
||||
if (args.size() != 6) {
|
||||
if (args.size() > 3) {
|
||||
if (args.size() != 5) {
|
||||
return (*cntx)->SendError(WrongNumArgsError("XRANGE"), kSyntaxErrType);
|
||||
}
|
||||
ToUpper(&args[4]);
|
||||
string_view opt = ArgS(args, 4);
|
||||
string_view val = ArgS(args, 5);
|
||||
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);
|
||||
|
|
|
@ -663,8 +663,8 @@ void SetCmd::RecordJournal(const SetParams& params, string_view key, string_view
|
|||
void StringFamily::Set(CmdArgList args, ConnectionContext* cntx) {
|
||||
set_qps.Inc();
|
||||
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view value = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view value = ArgS(args, 1);
|
||||
|
||||
SetCmd::SetParams sparams;
|
||||
sparams.memcache_flags = cntx->conn_state.memcache_flag;
|
||||
|
@ -672,7 +672,7 @@ void StringFamily::Set(CmdArgList args, ConnectionContext* cntx) {
|
|||
int64_t int_arg;
|
||||
SinkReplyBuilder* builder = cntx->reply_builder();
|
||||
|
||||
for (size_t i = 3; i < args.size(); ++i) {
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
ToUpper(&args[i]);
|
||||
|
||||
string_view cur_arg = ArgS(args, i);
|
||||
|
@ -768,8 +768,8 @@ void StringFamily::SetNx(CmdArgList args, ConnectionContext* cntx) {
|
|||
// change the value only if the key does not exist. Otherwise the function
|
||||
// will not modify it. in which case it would return 0
|
||||
// it would return to the caller 1 in case the key did not exists and was added
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view value = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view value = ArgS(args, 1);
|
||||
|
||||
SetCmd::SetParams sparams;
|
||||
sparams.flags |= SetCmd::SET_IF_NOTEXIST;
|
||||
|
@ -789,7 +789,7 @@ void StringFamily::SetNx(CmdArgList args, ConnectionContext* cntx) {
|
|||
void StringFamily::Get(CmdArgList args, ConnectionContext* cntx) {
|
||||
get_qps.Inc();
|
||||
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) { return OpGet(t->GetOpArgs(shard), key); };
|
||||
|
||||
|
@ -815,7 +815,7 @@ void StringFamily::Get(CmdArgList args, ConnectionContext* cntx) {
|
|||
void StringFamily::GetDel(CmdArgList args, ConnectionContext* cntx) {
|
||||
get_qps.Inc();
|
||||
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
bool run_del = true;
|
||||
|
@ -843,8 +843,8 @@ void StringFamily::GetDel(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StringFamily::GetSet(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view value = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view value = ArgS(args, 1);
|
||||
std::optional<string> prev_val;
|
||||
|
||||
SetCmd::SetParams sparams;
|
||||
|
@ -871,12 +871,12 @@ void StringFamily::GetSet(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StringFamily::GetEx(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
DbSlice::ExpireParams exp_params;
|
||||
int64_t int_arg = 0;
|
||||
|
||||
for (size_t i = 2; i < args.size(); i++) {
|
||||
for (size_t i = 1; i < args.size(); i++) {
|
||||
ToUpper(&args[i]);
|
||||
|
||||
string_view cur_arg = ArgS(args, i);
|
||||
|
@ -949,15 +949,13 @@ void StringFamily::GetEx(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StringFamily::Incr(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
return IncrByGeneric(key, 1, cntx);
|
||||
}
|
||||
|
||||
void StringFamily::IncrBy(CmdArgList args, ConnectionContext* cntx) {
|
||||
DCHECK_EQ(3u, args.size());
|
||||
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view sval = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view sval = ArgS(args, 1);
|
||||
int64_t val;
|
||||
|
||||
if (!absl::SimpleAtoi(sval, &val)) {
|
||||
|
@ -967,8 +965,8 @@ void StringFamily::IncrBy(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StringFamily::IncrByFloat(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view sval = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view sval = ArgS(args, 1);
|
||||
double val;
|
||||
|
||||
if (!absl::SimpleAtod(sval, &val)) {
|
||||
|
@ -991,13 +989,13 @@ void StringFamily::IncrByFloat(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StringFamily::Decr(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
return IncrByGeneric(key, -1, cntx);
|
||||
}
|
||||
|
||||
void StringFamily::DecrBy(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view sval = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view sval = ArgS(args, 1);
|
||||
int64_t val;
|
||||
|
||||
if (!absl::SimpleAtoi(sval, &val)) {
|
||||
|
@ -1050,8 +1048,8 @@ void StringFamily::IncrByGeneric(string_view key, int64_t val, ConnectionContext
|
|||
}
|
||||
|
||||
void StringFamily::ExtendGeneric(CmdArgList args, bool prepend, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view sval = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view sval = ArgS(args, 1);
|
||||
|
||||
if (cntx->protocol() == Protocol::REDIS) {
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
|
@ -1081,9 +1079,9 @@ void StringFamily::ExtendGeneric(CmdArgList args, bool prepend, ConnectionContex
|
|||
|
||||
/// (P)SETEX key seconds value
|
||||
void StringFamily::SetExGeneric(bool seconds, CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view ex = ArgS(args, 2);
|
||||
string_view value = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view ex = ArgS(args, 1);
|
||||
string_view value = ArgS(args, 2);
|
||||
int32_t unit_vals;
|
||||
|
||||
if (!absl::SimpleAtoi(ex, &unit_vals)) {
|
||||
|
@ -1113,7 +1111,7 @@ void StringFamily::SetExGeneric(bool seconds, CmdArgList args, ConnectionContext
|
|||
}
|
||||
|
||||
void StringFamily::MGet(CmdArgList args, ConnectionContext* cntx) {
|
||||
DCHECK_GT(args.size(), 1U);
|
||||
DCHECK_GE(args.size(), 1U);
|
||||
|
||||
Transaction* transaction = cntx->transaction;
|
||||
unsigned shard_count = shard_set->size();
|
||||
|
@ -1137,7 +1135,7 @@ void StringFamily::MGet(CmdArgList args, ConnectionContext* cntx) {
|
|||
CHECK_EQ(OpStatus::OK, result);
|
||||
|
||||
// reorder the responses back according to the order of their corresponding keys.
|
||||
vector<SinkReplyBuilder::OptResp> res(args.size() - 1);
|
||||
vector<SinkReplyBuilder::OptResp> res(args.size());
|
||||
|
||||
for (ShardId sid = 0; sid < shard_count; ++sid) {
|
||||
if (!transaction->IsActive(sid))
|
||||
|
@ -1157,7 +1155,7 @@ void StringFamily::MGet(CmdArgList args, ConnectionContext* cntx) {
|
|||
|
||||
auto& dest = res[indx].emplace();
|
||||
auto& src = *results[j];
|
||||
dest.key = ArgS(args, indx + 1);
|
||||
dest.key = ArgS(args, indx);
|
||||
dest.value = std::move(src.value);
|
||||
dest.mc_flag = src.mc_flag;
|
||||
dest.mc_ver = src.mc_ver;
|
||||
|
@ -1228,7 +1226,7 @@ void StringFamily::MSetNx(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StringFamily::StrLen(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<size_t> {
|
||||
OpResult<PrimeIterator> it_res = shard->db_slice().Find(t->GetDbContext(), key, OBJ_STRING);
|
||||
|
@ -1249,9 +1247,9 @@ void StringFamily::StrLen(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StringFamily::GetRange(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view from = ArgS(args, 2);
|
||||
string_view to = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view from = ArgS(args, 1);
|
||||
string_view to = ArgS(args, 2);
|
||||
int32_t start, end;
|
||||
|
||||
if (!absl::SimpleAtoi(from, &start) || !absl::SimpleAtoi(to, &end)) {
|
||||
|
@ -1273,9 +1271,9 @@ void StringFamily::GetRange(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void StringFamily::SetRange(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view offset = ArgS(args, 2);
|
||||
string_view value = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view offset = ArgS(args, 1);
|
||||
string_view value = ArgS(args, 2);
|
||||
int32_t start;
|
||||
|
||||
if (!absl::SimpleAtoi(offset, &start)) {
|
||||
|
@ -1347,33 +1345,33 @@ auto StringFamily::OpMGet(bool fetch_mcflag, bool fetch_mcver, const Transaction
|
|||
* X-RateLimit-Reset.
|
||||
*/
|
||||
void StringFamily::ClThrottle(CmdArgList args, ConnectionContext* cntx) {
|
||||
const string_view key = ArgS(args, 1);
|
||||
const string_view key = ArgS(args, 0);
|
||||
|
||||
// Allow max burst in number of tokens
|
||||
uint64_t max_burst;
|
||||
const string_view max_burst_str = ArgS(args, 2);
|
||||
const string_view max_burst_str = ArgS(args, 1);
|
||||
if (!absl::SimpleAtoi(max_burst_str, &max_burst)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
|
||||
// Emit count of tokens per period
|
||||
uint64_t count;
|
||||
const string_view count_str = ArgS(args, 3);
|
||||
const string_view count_str = ArgS(args, 2);
|
||||
if (!absl::SimpleAtoi(count_str, &count)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
|
||||
// Period of emitting count of tokens
|
||||
uint64_t period;
|
||||
const string_view period_str = ArgS(args, 4);
|
||||
const string_view period_str = ArgS(args, 3);
|
||||
if (!absl::SimpleAtoi(period_str, &period)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
|
||||
// Apply quantity of tokens now
|
||||
uint64_t quantity = 1;
|
||||
if (args.size() > 5) {
|
||||
const string_view quantity_str = ArgS(args, 5);
|
||||
if (args.size() > 4) {
|
||||
const string_view quantity_str = ArgS(args, 4);
|
||||
|
||||
if (!absl::SimpleAtoi(quantity_str, &quantity)) {
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
|
|
|
@ -344,12 +344,16 @@ RespVec BaseFamilyTest::TestConnWrapper::ParseResponse(bool fully_consumed) {
|
|||
tmp_str_vec_.emplace_back(new string{sink_.str()});
|
||||
auto& s = *tmp_str_vec_.back();
|
||||
auto buf = RespExpr::buffer(&s);
|
||||
uint32_t consumed = 0;
|
||||
|
||||
auto s_copy = s;
|
||||
|
||||
uint32_t consumed = 0;
|
||||
parser_.reset(new RedisParser{false}); // Client mode.
|
||||
RespVec res;
|
||||
RedisParser::Result st = parser_->Parse(buf, &consumed, &res);
|
||||
CHECK_EQ(RedisParser::OK, st);
|
||||
|
||||
CHECK_EQ(RedisParser::OK, st) << " response: \"" << s_copy << "\" (" << s_copy.size()
|
||||
<< " chars)";
|
||||
if (fully_consumed) {
|
||||
DCHECK_EQ(consumed, s.size()) << s;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ Transaction::~Transaction() {
|
|||
void Transaction::InitBase(DbIndex dbid, CmdArgList args) {
|
||||
global_ = false;
|
||||
db_index_ = dbid;
|
||||
cmd_with_full_args_ = args;
|
||||
full_args_ = args;
|
||||
local_result_ = OpStatus::OK;
|
||||
}
|
||||
|
||||
|
@ -83,21 +83,21 @@ void Transaction::InitGlobal() {
|
|||
|
||||
void Transaction::BuildShardIndex(KeyIndex key_index, bool rev_mapping,
|
||||
std::vector<PerShardCache>* out) {
|
||||
auto args = cmd_with_full_args_;
|
||||
auto args = full_args_;
|
||||
|
||||
auto& shard_index = *out;
|
||||
|
||||
auto add = [this, rev_mapping, &shard_index](uint32_t sid, uint32_t i) {
|
||||
string_view val = ArgS(cmd_with_full_args_, i);
|
||||
string_view val = ArgS(full_args_, i);
|
||||
shard_index[sid].args.push_back(val);
|
||||
if (rev_mapping)
|
||||
shard_index[sid].original_index.push_back(i - 1);
|
||||
shard_index[sid].original_index.push_back(i);
|
||||
};
|
||||
|
||||
if (key_index.bonus) {
|
||||
DCHECK(key_index.step == 1);
|
||||
uint32_t sid = Shard(ArgS(args, key_index.bonus), shard_data_.size());
|
||||
add(sid, key_index.bonus);
|
||||
uint32_t sid = Shard(ArgS(args, *key_index.bonus), shard_data_.size());
|
||||
add(sid, *key_index.bonus);
|
||||
}
|
||||
|
||||
for (unsigned i = key_index.start; i < key_index.end; ++i) {
|
||||
|
@ -157,7 +157,6 @@ void Transaction::InitShardData(absl::Span<const PerShardCache> shard_index, siz
|
|||
|
||||
void Transaction::InitMultiData(KeyIndex key_index) {
|
||||
DCHECK(multi_);
|
||||
auto args = cmd_with_full_args_;
|
||||
|
||||
if (multi_->mode == NON_ATOMIC)
|
||||
return;
|
||||
|
@ -184,9 +183,9 @@ void Transaction::InitMultiData(KeyIndex key_index) {
|
|||
// for eval. currently, we lock everything only during the eval call.
|
||||
if (multi_->IsIncrLocks() || !multi_->locks_recorded) {
|
||||
for (size_t i = key_index.start; i < key_index.end; i += key_index.step)
|
||||
lock_key(ArgS(args, i));
|
||||
if (key_index.bonus > 0)
|
||||
lock_key(ArgS(args, key_index.bonus));
|
||||
lock_key(ArgS(full_args_, i));
|
||||
if (key_index.bonus)
|
||||
lock_key(ArgS(full_args_, *key_index.bonus));
|
||||
}
|
||||
|
||||
multi_->locks_recorded = true;
|
||||
|
@ -195,22 +194,20 @@ void Transaction::InitMultiData(KeyIndex key_index) {
|
|||
}
|
||||
|
||||
void Transaction::StoreKeysInArgs(KeyIndex key_index, bool rev_mapping) {
|
||||
DCHECK_EQ(key_index.bonus, 0U);
|
||||
|
||||
auto args = cmd_with_full_args_;
|
||||
DCHECK(!key_index.bonus);
|
||||
DCHECK(key_index.step == 1u || key_index.step == 2u);
|
||||
|
||||
// even for a single key we may have multiple arguments per key (MSET).
|
||||
for (unsigned j = key_index.start; j < key_index.end; j++) {
|
||||
args_.push_back(ArgS(args, j));
|
||||
args_.push_back(ArgS(full_args_, j));
|
||||
if (key_index.step == 2)
|
||||
args_.push_back(ArgS(args, ++j));
|
||||
args_.push_back(ArgS(full_args_, ++j));
|
||||
}
|
||||
|
||||
if (rev_mapping) {
|
||||
reverse_index_.resize(args_.size());
|
||||
for (unsigned j = 0; j < reverse_index_.size(); ++j) {
|
||||
reverse_index_[j] = j + key_index.start - 1;
|
||||
reverse_index_[j] = j + key_index.start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +233,7 @@ void Transaction::StoreKeysInArgs(KeyIndex key_index, bool rev_mapping) {
|
|||
**/
|
||||
|
||||
void Transaction::InitByKeys(KeyIndex key_index) {
|
||||
auto args = cmd_with_full_args_;
|
||||
auto args = full_args_;
|
||||
|
||||
if (key_index.start == args.size()) { // eval with 0 keys.
|
||||
CHECK(absl::StartsWith(cid_->name(), "EVAL"));
|
||||
|
@ -266,7 +263,7 @@ void Transaction::InitByKeys(KeyIndex key_index) {
|
|||
|
||||
shard_data_.resize(shard_set->size()); // shard_data isn't sparse, so we must allocate for all :(
|
||||
CHECK(key_index.step == 1 || key_index.step == 2);
|
||||
DCHECK(key_index.step == 1 || (args.size() % 2) == 1);
|
||||
DCHECK(key_index.step == 1 || (args.size() % 2) == 0);
|
||||
|
||||
// Safe, because flow below is not preemptive.
|
||||
auto& shard_index = tmp_space.GetShardIndex(shard_data_.size());
|
||||
|
@ -299,7 +296,7 @@ void Transaction::InitByKeys(KeyIndex key_index) {
|
|||
// Validation. Check reverse mapping was built correctly.
|
||||
if (needs_reverse_mapping) {
|
||||
for (size_t i = 0; i < args_.size(); ++i) {
|
||||
DCHECK_EQ(args_[i], ArgS(args, 1 + reverse_index_[i])); // 1 for the commandname.
|
||||
DCHECK_EQ(args_[i], ArgS(args, reverse_index_[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,7 +319,6 @@ OpStatus Transaction::InitByArgs(DbIndex index, CmdArgList args) {
|
|||
return OpStatus::OK;
|
||||
}
|
||||
|
||||
CHECK_GT(args.size(), 1U); // first entry is the command name.
|
||||
DCHECK_EQ(unique_shard_cnt_, 0u);
|
||||
DCHECK(args_.empty());
|
||||
|
||||
|
@ -1360,11 +1356,11 @@ void Transaction::LogAutoJournalOnShard(EngineShard* shard) {
|
|||
|
||||
// TODO: Handle complex commands like LMPOP correctly once they are implemented.
|
||||
journal::Entry::Payload entry_payload;
|
||||
|
||||
string_view cmd{cid_->name()};
|
||||
if (unique_shard_cnt_ == 1 || args_.empty()) {
|
||||
CHECK(!cmd_with_full_args_.empty());
|
||||
entry_payload = cmd_with_full_args_;
|
||||
entry_payload = make_pair(cmd, full_args_);
|
||||
} else {
|
||||
auto cmd = facade::ToSV(cmd_with_full_args_.front());
|
||||
entry_payload = make_pair(cmd, GetShardArgs(shard->shard_id()));
|
||||
}
|
||||
LogJournalOnShard(shard, std::move(entry_payload), unique_shard_cnt_, false, true);
|
||||
|
@ -1411,17 +1407,20 @@ OpResult<KeyIndex> DetermineKeys(const CommandId* cid, CmdArgList args) {
|
|||
if (cid->opt_mask() & CO::VARIADIC_KEYS) {
|
||||
// ZUNION/INTER <num_keys> <key1> [<key2> ...]
|
||||
// EVAL <script> <num_keys>
|
||||
if (args.size() < 3) {
|
||||
if (args.size() < 2) {
|
||||
return OpStatus::SYNTAX_ERR;
|
||||
}
|
||||
|
||||
string_view name{cid->name()};
|
||||
|
||||
if (absl::EndsWith(name, "STORE")) {
|
||||
key_index.bonus = 1; // Z<xxx>STORE commands
|
||||
}
|
||||
if (absl::EndsWith(name, "STORE"))
|
||||
key_index.bonus = 0; // Z<xxx>STORE <key> commands
|
||||
|
||||
unsigned num_keys_index = absl::StartsWith(name, "EVAL") ? 2 : key_index.bonus + 1;
|
||||
unsigned num_keys_index;
|
||||
if (absl::StartsWith(name, "EVAL"))
|
||||
num_keys_index = 1;
|
||||
else
|
||||
num_keys_index = key_index.bonus ? *key_index.bonus + 1 : 0;
|
||||
|
||||
string_view num = ArgS(args, num_keys_index);
|
||||
if (!absl::SimpleAtoi(num, &num_custom_keys) || num_custom_keys < 0)
|
||||
|
@ -1432,12 +1431,12 @@ OpResult<KeyIndex> DetermineKeys(const CommandId* cid, CmdArgList args) {
|
|||
}
|
||||
|
||||
if (cid->first_key_pos() > 0) {
|
||||
key_index.start = cid->first_key_pos();
|
||||
key_index.start = cid->first_key_pos() - 1;
|
||||
int last = cid->last_key_pos();
|
||||
if (num_custom_keys >= 0) {
|
||||
key_index.end = key_index.start + num_custom_keys;
|
||||
} else {
|
||||
key_index.end = last > 0 ? last + 1 : (int(args.size()) + 1 + last);
|
||||
key_index.end = last > 0 ? last : (int(args.size()) + last + 1);
|
||||
}
|
||||
key_index.step = cid->key_arg_step();
|
||||
|
||||
|
|
|
@ -532,7 +532,7 @@ class Transaction {
|
|||
absl::InlinedVector<std::string_view, 4> args_;
|
||||
|
||||
// Stores the full undivided command.
|
||||
CmdArgList cmd_with_full_args_;
|
||||
CmdArgList full_args_;
|
||||
|
||||
// True if NO_AUTOJOURNAL command asked to enable auto journal
|
||||
std::atomic<bool> renabled_auto_journal_ = false;
|
||||
|
|
|
@ -931,7 +931,7 @@ OpResult<void> FillAggType(string_view agg, SetOpArgs* op_args) {
|
|||
|
||||
// Parse functions return the number of arguments read from CmdArgList
|
||||
OpResult<unsigned> ParseAggregate(CmdArgList args, bool store, SetOpArgs* op_args) {
|
||||
if (args.size() < 2) {
|
||||
if (args.size() < 1) {
|
||||
return OpStatus::SYNTAX_ERR;
|
||||
}
|
||||
|
||||
|
@ -973,7 +973,7 @@ OpResult<unsigned> ParseWithScores(CmdArgList args, SetOpArgs* op_args) {
|
|||
}
|
||||
|
||||
OpResult<SetOpArgs> ParseSetOpArgs(CmdArgList args, bool store) {
|
||||
string_view num_keys_str = store ? ArgS(args, 2) : ArgS(args, 1);
|
||||
string_view num_keys_str = store ? ArgS(args, 1) : ArgS(args, 0);
|
||||
SetOpArgs op_args;
|
||||
|
||||
auto parsed = ParseKeyCount(num_keys_str, &op_args);
|
||||
|
@ -981,7 +981,7 @@ OpResult<SetOpArgs> ParseSetOpArgs(CmdArgList args, bool store) {
|
|||
return parsed.status();
|
||||
}
|
||||
|
||||
unsigned opt_args_start = op_args.num_keys + (store ? 3 : 2);
|
||||
unsigned opt_args_start = op_args.num_keys + (store ? 2 : 1);
|
||||
DCHECK_LE(opt_args_start, args.size()); // Checked inside DetermineKeys
|
||||
|
||||
for (size_t i = opt_args_start; i < args.size(); ++i) {
|
||||
|
@ -1033,7 +1033,7 @@ void ZUnionFamilyInternal(CmdArgList args, bool store, ConnectionContext* cntx)
|
|||
|
||||
vector<OpResult<ScoredMap>> maps(shard_set->size());
|
||||
|
||||
string_view dest_key = ArgS(args, 1);
|
||||
string_view dest_key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
maps[shard->shard_id()] = OpUnion(shard, t, dest_key, op_args.agg_type, op_args.weights, store);
|
||||
|
@ -1096,10 +1096,10 @@ bool ParseLimit(string_view offset_str, string_view limit_str, ZSetFamily::Range
|
|||
} // namespace
|
||||
|
||||
void ZSetFamily::ZAdd(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
ZParams zparams;
|
||||
size_t i = 2;
|
||||
size_t i = 1;
|
||||
for (; i < args.size() - 1; ++i) {
|
||||
ToUpper(&args[i]);
|
||||
|
||||
|
@ -1192,7 +1192,7 @@ void ZSetFamily::ZAdd(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZCard(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) -> OpResult<uint32_t> {
|
||||
OpResult<PrimeIterator> find_res = shard->db_slice().Find(t->GetDbContext(), key, OBJ_ZSET);
|
||||
|
@ -1213,10 +1213,10 @@ void ZSetFamily::ZCard(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZCount(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
string_view min_s = ArgS(args, 2);
|
||||
string_view max_s = ArgS(args, 3);
|
||||
string_view min_s = ArgS(args, 1);
|
||||
string_view max_s = ArgS(args, 2);
|
||||
|
||||
ScoreInterval si;
|
||||
if (!ParseBound(min_s, &si.first) || !ParseBound(max_s, &si.second)) {
|
||||
|
@ -1236,11 +1236,11 @@ void ZSetFamily::ZCount(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZIncrBy(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view score_arg = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view score_arg = ArgS(args, 1);
|
||||
|
||||
ScoredMemberView scored_member;
|
||||
scored_member.second = ArgS(args, 3);
|
||||
scored_member.second = ArgS(args, 2);
|
||||
|
||||
if (!absl::SimpleAtod(score_arg, &scored_member.first)) {
|
||||
VLOG(1) << "Bad score:" << score_arg << "|";
|
||||
|
@ -1275,7 +1275,7 @@ void ZSetFamily::ZIncrBy(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZInterStore(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view dest_key = ArgS(args, 1);
|
||||
string_view dest_key = ArgS(args, 0);
|
||||
OpResult<SetOpArgs> op_args_res = ParseSetOpArgs(args, true);
|
||||
|
||||
if (!op_args_res) {
|
||||
|
@ -1349,10 +1349,10 @@ void ZSetFamily::ZPopMin(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZLexCount(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
string_view min_s = ArgS(args, 2);
|
||||
string_view max_s = ArgS(args, 3);
|
||||
string_view min_s = ArgS(args, 1);
|
||||
string_view max_s = ArgS(args, 2);
|
||||
|
||||
LexInterval li;
|
||||
if (!ParseLexBound(min_s, &li.first) || !ParseLexBound(max_s, &li.second)) {
|
||||
|
@ -1374,7 +1374,7 @@ void ZSetFamily::ZLexCount(CmdArgList args, ConnectionContext* cntx) {
|
|||
void ZSetFamily::ZRange(CmdArgList args, ConnectionContext* cntx) {
|
||||
RangeParams range_params;
|
||||
|
||||
for (size_t i = 4; i < args.size(); ++i) {
|
||||
for (size_t i = 3; i < args.size(); ++i) {
|
||||
ToUpper(&args[i]);
|
||||
|
||||
string_view cur_arg = ArgS(args, i);
|
||||
|
@ -1415,7 +1415,7 @@ void ZSetFamily::ZRevRange(CmdArgList args, ConnectionContext* cntx) {
|
|||
RangeParams range_params;
|
||||
range_params.reverse = true;
|
||||
|
||||
for (size_t i = 4; i < args.size(); ++i) {
|
||||
for (size_t i = 3; i < args.size(); ++i) {
|
||||
ToUpper(&args[i]);
|
||||
|
||||
string_view cur_arg = ArgS(args, i);
|
||||
|
@ -1452,15 +1452,15 @@ void ZSetFamily::ZRangeByLexInternal(CmdArgList args, bool reverse, ConnectionCo
|
|||
range_params.interval_type = RangeParams::IntervalType::LEX;
|
||||
range_params.reverse = reverse;
|
||||
|
||||
if (args.size() > 4) {
|
||||
if (args.size() != 7)
|
||||
if (args.size() > 3) {
|
||||
if (args.size() != 6)
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
|
||||
ToUpper(&args[4]);
|
||||
if (ArgS(args, 4) != "LIMIT")
|
||||
ToUpper(&args[3]);
|
||||
if (ArgS(args, 3) != "LIMIT")
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
|
||||
if (!ParseLimit(ArgS(args, 5), ArgS(args, 6), &range_params))
|
||||
if (!ParseLimit(ArgS(args, 4), ArgS(args, 5), &range_params))
|
||||
return (*cntx)->SendError(kInvalidIntErr);
|
||||
}
|
||||
range_params.offset = offset;
|
||||
|
@ -1474,9 +1474,9 @@ void ZSetFamily::ZRangeByScore(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZRemRangeByRank(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view min_s = ArgS(args, 2);
|
||||
string_view max_s = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view min_s = ArgS(args, 1);
|
||||
string_view max_s = ArgS(args, 2);
|
||||
|
||||
IndexInterval ii;
|
||||
if (!SimpleAtoi(min_s, &ii.first) || !SimpleAtoi(max_s, &ii.second)) {
|
||||
|
@ -1489,9 +1489,9 @@ void ZSetFamily::ZRemRangeByRank(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZRemRangeByScore(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view min_s = ArgS(args, 2);
|
||||
string_view max_s = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view min_s = ArgS(args, 1);
|
||||
string_view max_s = ArgS(args, 2);
|
||||
|
||||
ScoreInterval si;
|
||||
if (!ParseBound(min_s, &si.first) || !ParseBound(max_s, &si.second)) {
|
||||
|
@ -1506,9 +1506,9 @@ void ZSetFamily::ZRemRangeByScore(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZRemRangeByLex(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view min_s = ArgS(args, 2);
|
||||
string_view max_s = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view min_s = ArgS(args, 1);
|
||||
string_view max_s = ArgS(args, 2);
|
||||
|
||||
LexInterval li;
|
||||
if (!ParseLexBound(min_s, &li.first) || !ParseLexBound(max_s, &li.second)) {
|
||||
|
@ -1523,11 +1523,11 @@ void ZSetFamily::ZRemRangeByLex(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZRem(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
absl::InlinedVector<string_view, 8> members(args.size() - 2);
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
members[i - 2] = ArgS(args, i);
|
||||
absl::InlinedVector<string_view, 8> members(args.size() - 1);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
members[i - 1] = ArgS(args, i);
|
||||
}
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
|
@ -1543,8 +1543,8 @@ void ZSetFamily::ZRem(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZScore(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view member = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view member = ArgS(args, 1);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpScore(t->GetOpArgs(shard), key, member);
|
||||
|
@ -1561,11 +1561,11 @@ void ZSetFamily::ZScore(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZMScore(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
absl::InlinedVector<string_view, 8> members(args.size() - 2);
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
members[i - 2] = ArgS(args, i);
|
||||
absl::InlinedVector<string_view, 8> members(args.size() - 1);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
members[i - 1] = ArgS(args, i);
|
||||
}
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
|
@ -1590,8 +1590,8 @@ void ZSetFamily::ZMScore(CmdArgList args, ConnectionContext* cntx) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZScan(CmdArgList args, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view token = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view token = ArgS(args, 1);
|
||||
|
||||
uint64_t cursor = 0;
|
||||
|
||||
|
@ -1599,7 +1599,7 @@ void ZSetFamily::ZScan(CmdArgList args, ConnectionContext* cntx) {
|
|||
return (*cntx)->SendError("invalid cursor");
|
||||
}
|
||||
|
||||
OpResult<ScanOpts> ops = ScanOpts::TryFrom(args.subspan(3));
|
||||
OpResult<ScanOpts> ops = ScanOpts::TryFrom(args.subspan(2));
|
||||
if (!ops) {
|
||||
DVLOG(1) << "Scan invalid args - return " << ops << " to the user";
|
||||
return (*cntx)->SendError(ops.status());
|
||||
|
@ -1635,7 +1635,7 @@ void ZSetFamily::ZRangeByScoreInternal(CmdArgList args, bool reverse, Connection
|
|||
RangeParams range_params;
|
||||
range_params.interval_type = RangeParams::IntervalType::SCORE;
|
||||
range_params.reverse = reverse;
|
||||
if (!ParseRangeByScoreParams(args.subspan(4), &range_params)) {
|
||||
if (!ParseRangeByScoreParams(args.subspan(3), &range_params)) {
|
||||
return (*cntx)->SendError(kSyntaxErr);
|
||||
}
|
||||
ZRangeGeneric(args, range_params, cntx);
|
||||
|
@ -1667,9 +1667,9 @@ void ZSetFamily::ZRemRangeGeneric(string_view key, const ZRangeSpec& range_spec,
|
|||
}
|
||||
|
||||
void ZSetFamily::ZRangeGeneric(CmdArgList args, RangeParams range_params, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view min_s = ArgS(args, 2);
|
||||
string_view max_s = ArgS(args, 3);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view min_s = ArgS(args, 1);
|
||||
string_view max_s = ArgS(args, 2);
|
||||
|
||||
ZRangeSpec range_spec;
|
||||
range_spec.params = range_params;
|
||||
|
@ -1711,8 +1711,8 @@ void ZSetFamily::ZRangeGeneric(CmdArgList args, RangeParams range_params, Connec
|
|||
}
|
||||
|
||||
void ZSetFamily::ZRankGeneric(CmdArgList args, bool reverse, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view member = ArgS(args, 2);
|
||||
string_view key = ArgS(args, 0);
|
||||
string_view member = ArgS(args, 1);
|
||||
|
||||
auto cb = [&](Transaction* t, EngineShard* shard) {
|
||||
return OpRank(t->GetOpArgs(shard), key, member, reverse);
|
||||
|
@ -1751,7 +1751,7 @@ bool ZSetFamily::ParseRangeByScoreParams(CmdArgList args, RangeParams* params) {
|
|||
}
|
||||
|
||||
void ZSetFamily::ZPopMinMax(CmdArgList args, bool reverse, ConnectionContext* cntx) {
|
||||
string_view key = ArgS(args, 1);
|
||||
string_view key = ArgS(args, 0);
|
||||
|
||||
RangeParams range_params;
|
||||
range_params.reverse = reverse;
|
||||
|
@ -1760,8 +1760,8 @@ void ZSetFamily::ZPopMinMax(CmdArgList args, bool reverse, ConnectionContext* cn
|
|||
range_spec.params = range_params;
|
||||
|
||||
TopNScored sc = 1;
|
||||
if (args.size() > 2) {
|
||||
string_view count = ArgS(args, 2);
|
||||
if (args.size() > 1) {
|
||||
string_view count = ArgS(args, 1);
|
||||
if (!SimpleAtoi(count, &sc)) {
|
||||
return (*cntx)->SendError(kUintErr);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue