Add custom command config checking

- add config sample(including Read mode)
- apply @fortue's suggestion to check exclusive mode and key postion
This commit is contained in:
Yoon 2018-04-10 17:07:47 +09:00
parent aa013991f7
commit 95f4580ccf
3 changed files with 56 additions and 31 deletions

View File

@ -1,65 +1,83 @@
# CustomCommand section must be defined before Latency monitor to support all commands # CustomCommand section must be defined before Latency monitor to support all commands
# #
# NOTE: only support maximum 16 custom commands # NOTE: only support maximum 16 custom commands
#
# [...] must be specify
# (...) optional. it has default value
#
# CustomCommand [alias1] { ## module alias. just a delimter
# [command1] { ## command string, must be lower case. i.e. setnx, expire, ...
# (minArgs) (val) ## minimum arguments(including command itself). default is 2(key only)
# (maxArgs) (val) ## maximum arguments(including command itself). default is 2(key only)
# (mode) (val) ## a command mode Read/Write/Admin is exclusive. default is Write.
# }
# [command2] {
# ...
# }
# ...
# }
#
# default key position is first parameter. i.e. command1 key ...
# if you want to use other position, add KeyAt2(key is second) or KeyAt3(key is third) to mode with '|'
# i.e. mode Write|KeyAt2
#
# in case of 'mode KeyAt2', it will resolved as Write|KeyAt2
CustomCommand { # from redis source src/modules/hello.c
# from redis source src/modules/hello.c CustomCommand hello {
# hello.push.native key value # hello.push.native key value
hello.push.native { # name of command, must be lowercase. hello.push.native {
# key parameter is located at first argument. i.e. command key ... minArgs 3
# Currently support only 1 key with first argument. maxArgs 3
minArgs 3 # minimum arguments(including command itself), default is 2(key only) mode Write
maxArgs 3 # maximum arguments(including command itself), default is 2(key only)
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 = Write are default values # just skipped since minArgs = 2, maxArgs = 2, mode = Write are default values
hello.repl2 { hello.repl2 {
} }
# hello.toggle.case key # hello.toggle.case key
# same as hello.repl2
hello.toggle.case { hello.toggle.case {
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 Write
} }
# hello.zsumrange key startscore endscore # hello.zsumrange key startscore endscore
hello.zsumrange { hello.zsumrange {
minArgs 4 minArgs 4
maxArgs 4 maxArgs 4
mode Write mode Read
} }
# 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 Write mode Read
} }
# hello.hcopy key srcfield dstfield # hello.hcopy key srcfield dstfield
hello.hcopy { hello.hcopy {
minArgs 4 minArgs 4
maxArgs 4 maxArgs 4
mode Write
} }
}
# from redis source src/modules/hellotype.c # from redis source src/modules/hellotype.c
CustomCommand hellotype {
# hellotype.insert key value # hellotype.insert key value
hello.insert { hellotype.insert {
minArgs 3 minArgs 3
maxArgs 3 maxArgs 3
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 Write mode Read
} }
# hellotype.len key # hellotype.len key
hello.len { hello.len {
mode Write mode Read
} }
} }

View File

@ -380,9 +380,6 @@ void Conf::setCustomCommand(const ConfParser::Node* node)
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) {
Throw(InvalidValue, "%s:%d CustomCommand.Command require scope value", 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)) {
@ -405,18 +402,14 @@ bool Conf::setCommandMode(int& mode, const char* name, const ConfParser::Node* n
mode = defaultMode; mode = defaultMode;
} else { } else {
mode = 0; 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)) {
used++;
mode |= Command::Write; mode |= Command::Write;
} else if ((strcasecmp(mask.c_str(), "Read") == 0)) { } else if ((strcasecmp(mask.c_str(), "Read") == 0)) {
used++;
mode |= Command::Read; mode |= Command::Read;
} else if ((strcasecmp(mask.c_str(), "Admin") == 0)) { } else if ((strcasecmp(mask.c_str(), "Admin") == 0)) {
used++;
mode |= Command::Admin; 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;
@ -426,10 +419,24 @@ bool Conf::setCommandMode(int& mode, const char* name, const ConfParser::Node* n
Throw(InvalidValue, "%s:%d unknown mode %s", n->file, n->line, mask.c_str()); Throw(InvalidValue, "%s:%d unknown mode %s", n->file, n->line, mask.c_str());
} }
} }
if (used == 0) { switch (mode & Command::KeyMask) {
Throw(InvalidValue, "%s:%d %s command require exclusive mode", n->file, n->line, name); case 0:
} else if (used > 1) { case Command::KeyAt2:
Throw(InvalidValue, "%s:%d %s command duplicated exclusive mode", n->file, n->line, name); case Command::KeyAt3:
break;
default:
Throw(InvalidValue, "%s:%d %s require exclusive key pos", n->file, n->line, name);
}
switch (mode & Command::AuthMask) {
case 0:
mode |= Command::Write;
break;
case Command::Read:
case Command::Write:
case Command::Admin:
break;
default:
Throw(InvalidValue, "%s:%d %s require exclusive mode", n->file, n->line, name);
} }
} }
return true; return true;

View File

@ -98,7 +98,7 @@ public:
Buffer* output(Buffer* buf) const; Buffer* output(Buffer* buf) const;
private: private:
String mName; String mName;
const std::bitset<Command::Sentinel>* mCmds; const std::bitset<Command::AvailableCommands>* mCmds;
std::vector<TimeSpan> mTimeSpan; std::vector<TimeSpan> mTimeSpan;
TimeSpan mLast; TimeSpan mLast;
}; };