Add custom command exclusive mode checking

This commit is contained in:
Yoon 2018-04-10 10:32:59 +09:00
parent 75228f3272
commit aa013991f7
2 changed files with 52 additions and 46 deletions

View File

@ -8,42 +8,41 @@ CustomCommand {
hello.push.native { # name of command, must be lowercase. hello.push.native { # name of command, must be lowercase.
# key parameter is located at first argument. i.e. command key ... # key parameter is located at first argument. i.e. command key ...
# Currently support only 1 key with first argument. # Currently support only 1 key with first argument.
minArgs 3 # minimum arguments(including command itself), default is 2(key only) minArgs 3 # minimum arguments(including command itself), default is 2(key only)
maxArgs 3 # maximum arguments(including command itself), default is 2(key only) maxArgs 3 # maximum arguments(including command itself), default is 2(key only)
mode Read,Write # a command mode Read/Write/Admin is exclusive, default is Write mode Write # a command mode Read/Write/Admin is exclusive, default is Write
} }
# hello.repl2 <list-key> # hello.repl2 <list-key>
# just skipped since minArgs = 2, maxArgs = 2, mode = Read,Write are default values # just skipped since minArgs = 2, maxArgs = 2, mode = Write are default values
hello.repl2 { hello.repl2 {
mode Read,Write
} }
# hello.toggle.case key # hello.toggle.case key
hello.toggle.case { hello.toggle.case {
mode Read,Write mode Write
} }
# hello.more.expire key milliseconds # hello.more.expire key milliseconds
hello.more.expire { hello.more.expire {
minArgs 3 minArgs 3
maxArgs 3 maxArgs 3
mode Read,Write mode Write
} }
# hello.zsumrange key startscore endscore # hello.zsumrange key startscore endscore
hello.zsumrange { hello.zsumrange {
minArgs 4 minArgs 4
maxArgs 4 maxArgs 4
mode Read,Write mode Write
} }
# hello.lexrange key min_lex max_lex min_age max_age # hello.lexrange key min_lex max_lex min_age max_age
hello.lexrange { hello.lexrange {
minArgs 6 minArgs 6
maxArgs 6 maxArgs 6
mode Read,Write mode Write
} }
# hello.hcopy key srcfield dstfield # hello.hcopy key srcfield dstfield
hello.hcopy { hello.hcopy {
minArgs 4 minArgs 4
maxArgs 4 maxArgs 4
mode Read,Write mode Write
} }
# from redis source src/modules/hellotype.c # from redis source src/modules/hellotype.c
@ -51,16 +50,16 @@ CustomCommand {
hello.insert { hello.insert {
minArgs 3 minArgs 3
maxArgs 3 maxArgs 3
mode Read,Write mode Write
} }
# hellotype.range key first count # hellotype.range key first count
hellotype.range { hellotype.range {
minArgs 4 minArgs 4
maxArgs 4 maxArgs 4
mode Read,Write mode Write
} }
# hellotype.len key # hellotype.len key
hello.len { hello.len {
mode Read,Write mode Write
} }
} }

View File

@ -373,59 +373,66 @@ void Conf::setDataCenter(const ConfParser::Node* node)
void Conf::setCustomCommand(const ConfParser::Node* node) void Conf::setCustomCommand(const ConfParser::Node* node)
{ {
if (!node->sub) { if (!node->sub) {
Throw(InvalidValue, "%s:%d CustomCommand require scope value", node->file, node->line); Throw(InvalidValue, "%s:%d CustomCommand require scope value", node->file, node->line);
} }
for (auto p = node->sub; p; p = p->next) { for (auto p = node->sub; p; p = p->next) {
mCustomCommands.push_back(CustomCommandConf{}); mCustomCommands.push_back(CustomCommandConf{});
auto& cc = mCustomCommands.back(); auto& cc = mCustomCommands.back();
CustomCommandConf::init(cc, p->key.c_str(), Command::Sentinel); CustomCommandConf::init(cc, p->key.c_str(), Command::Sentinel);
auto s = p->sub; auto s = p->sub;
if (!s) { if (!s) {
Throw(InvalidValue, "%s:%d CustomCommand.Command require scope value", Throw(InvalidValue, "%s:%d CustomCommand.Command require scope value", node->file, node->line);
node->file, node->line); }
} for (;s ; s = s->next) {
for (;s ; s = s->next) { if (setInt(cc.cmd.minArgs, "minArgs", s, 2)) {
if (setInt(cc.cmd.minArgs, "minArgs", s, 2)) { } else if (setInt(cc.cmd.maxArgs, "maxArgs", s, 2, 9999)) {
} else if (setInt(cc.cmd.maxArgs, "maxArgs", s, 2, 9999)) { } else if (setCommandMode(cc.cmd.mode, "mode", s)) {
} else if (setCommandMode(cc.cmd.mode, "mode", s)) { } else {
} else { Throw(UnknownKey, "%s:%d unknown key %s", s->file, s->line, s->key.c_str());
Throw(UnknownKey, "%s:%d unknown key %s", }
s->file, s->line, s->key.c_str()); }
} Command::addCustomCommand(&cc.cmd);
}
Command::addCustomCommand(&cc.cmd);
} }
} }
bool Conf::setCommandMode(int& mode, const char* name, const ConfParser::Node* n, const int defaultMode) bool Conf::setCommandMode(int& mode, const char* name, const ConfParser::Node* n, const int defaultMode)
{ {
if (strcasecmp(name, n->key.c_str()) == 0) { if (strcasecmp(name, n->key.c_str()) != 0) {
if (n->val.size() == 0) { return false;
mode = defaultMode; }
} else {
mode = Command::Unknown; if (n->val.size() == 0) {
} mode = defaultMode;
} else {
mode = 0;
int used = 0;
std::string mask; std::string mask;
std::istringstream is(n->val); std::istringstream is(n->val);
while (std::getline(is, mask, ',')) { while (std::getline(is, mask, ',')) {
if ((strcasecmp(mask.c_str(), "Write") == 0)) { if ((strcasecmp(mask.c_str(), "Write") == 0)) {
mode |= Command::Write; used++;
mode |= Command::Write;
} else if ((strcasecmp(mask.c_str(), "Read") == 0)) { } else if ((strcasecmp(mask.c_str(), "Read") == 0)) {
mode |= Command::Read; used++;
mode |= Command::Read;
} else if ((strcasecmp(mask.c_str(), "Admin") == 0)) { } else if ((strcasecmp(mask.c_str(), "Admin") == 0)) {
mode |= Command::Admin; used++;
mode |= Command::Admin;
} else if ((strcasecmp(mask.c_str(), "KeyAt2") == 0)) { } else if ((strcasecmp(mask.c_str(), "KeyAt2") == 0)) {
mode |= Command::KeyAt2; mode |= Command::KeyAt2;
} else if ((strcasecmp(mask.c_str(), "KeyAt3") == 0)) { } else if ((strcasecmp(mask.c_str(), "KeyAt3") == 0)) {
mode |= Command::KeyAt3; mode |= Command::KeyAt3;
} else { } else {
Throw(InvalidValue, "%s:%d %s %s is not an mode", Throw(InvalidValue, "%s:%d unknown mode %s", n->file, n->line, mask.c_str());
n->file, n->line, name, n->val.c_str());
} }
} }
return true; if (used == 0) {
Throw(InvalidValue, "%s:%d %s command require exclusive mode", n->file, n->line, name);
} else if (used > 1) {
Throw(InvalidValue, "%s:%d %s command duplicated exclusive mode", n->file, n->line, name);
}
} }
return false; return true;
} }
void Conf::setDC(DCConf& dc, const ConfParser::Node* node) void Conf::setDC(DCConf& dc, const ConfParser::Node* node)