This commit is contained in:
Yoon 2018-04-09 03:50:58 +00:00 committed by GitHub
commit 22bc20f82e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 180 additions and 6 deletions

66
conf/command.conf Normal file
View File

@ -0,0 +1,66 @@
# CustomCommand section must be defined before Latency monitor to support all commands
#
# NOTE: only support maximum 16 custom commands
CustomCommand {
# from redis source src/modules/hello.c
# hello.push.native key value
hello.push.native { # name of command, must be lowercase.
# key parameter is located at first argument. i.e. command key ...
# Currently support only 1 key with first argument.
minArgs 3 # minimum 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
}
# hello.repl2 <list-key>
# just skipped since minArgs = 2, maxArgs = 2, mode = Read,Write are default values
hello.repl2 {
mode Read,Write
}
# hello.toggle.case key
hello.toggle.case {
mode Read,Write
}
# hello.more.expire key milliseconds
hello.more.expire {
minArgs 3
maxArgs 3
mode Read,Write
}
# hello.zsumrange key startscore endscore
hello.zsumrange {
minArgs 4
maxArgs 4
mode Read,Write
}
# hello.lexrange key min_lex max_lex min_age max_age
hello.lexrange {
minArgs 6
maxArgs 6
mode Read,Write
}
# hello.hcopy key srcfield dstfield
hello.hcopy {
minArgs 4
maxArgs 4
mode Read,Write
}
# from redis source src/modules/hellotype.c
# hellotype.insert key value
hello.insert {
minArgs 3
maxArgs 3
mode Read,Write
}
# hellotype.range key first count
hellotype.range {
minArgs 4
maxArgs 4
mode Read,Write
}
# hellotype.len key
hello.len {
mode Read,Write
}
}

View File

@ -93,6 +93,11 @@ Include try.conf
# Include dc.conf # Include dc.conf
################################### COMMAND ####################################
## Custom command define, see command.conf
## must be defined before Latency monitor
#Include command.conf
################################### LATENCY #################################### ################################### LATENCY ####################################
## Latency monitor define, see latency.conf ## Latency monitor define, see latency.conf
Include latency.conf Include latency.conf

View File

@ -10,7 +10,7 @@
#include "String.h" #include "String.h"
#include "Command.h" #include "Command.h"
const Command Command::CmdPool[Sentinel] = { Command Command::CmdPool[AvailableCommands] = {
{None, "", 0, MaxArgs, Read}, {None, "", 0, MaxArgs, Read},
{Ping, "ping", 1, 2, Read}, {Ping, "ping", 1, 2, Read},
{PingServ, "ping", 1, 2, Inner}, {PingServ, "ping", 1, 2, Inner},
@ -171,11 +171,14 @@ const Command Command::CmdPool[Sentinel] = {
{SubMsg, "\000SubMsg", 0, 0, Admin} {SubMsg, "\000SubMsg", 0, 0, Admin}
}; };
int Command::Sentinel = Command::MaxCommands;
Command::CommandMap Command::CmdMap; Command::CommandMap Command::CmdMap;
void Command::init() void Command::init()
{ {
int type = 0; int type = 0;
for (auto& i : CmdPool) { for (auto j = 0; j < MaxCommands; j++) {
const auto& i = CmdPool[j];
if (i.type != type) { if (i.type != type) {
Throw(InitFail, "command %s unmatch the index in commands table", i.name); Throw(InitFail, "command %s unmatch the index in commands table", i.name);
} }
@ -187,3 +190,15 @@ void Command::init()
} }
} }
void Command::addCustomCommand(const Command *p) {
if (Sentinel >= AvailableCommands) {
Throw(InitFail, "too many custom commands(>%d)", MaxCustomCommands);
}
if (nullptr != find(p->name)) {
Throw(InitFail, "custom command %s is duplicated", p->name);
}
CmdPool[Sentinel] = *p;
CmdMap[p->name] = &CmdPool[Sentinel];
Sentinel++;
}

View File

@ -8,6 +8,7 @@
#define _PREDIXY_COMMAND_H_ #define _PREDIXY_COMMAND_H_
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "Exception.h" #include "Exception.h"
#include "HashFunc.h" #include "HashFunc.h"
@ -189,7 +190,9 @@ public:
Unsubscribe, Unsubscribe,
SubMsg, SubMsg,
Sentinel MaxCommands,
MaxCustomCommands = 16,
AvailableCommands = MaxCommands + MaxCustomCommands,
}; };
enum Mode enum Mode
{ {
@ -242,6 +245,7 @@ public:
if (cursor < Sentinel) { if (cursor < Sentinel) {
return &CmdPool[cursor++]; return &CmdPool[cursor++];
} }
return nullptr; return nullptr;
} }
static const Command* find(const String& cmd) static const Command* find(const String& cmd)
@ -249,9 +253,11 @@ public:
auto it = CmdMap.find(cmd); auto it = CmdMap.find(cmd);
return it == CmdMap.end() ? nullptr : it->second; return it == CmdMap.end() ? nullptr : it->second;
} }
static void addCustomCommand(const Command *pc);
static int Sentinel;
private: private:
static const int MaxArgs = 100000000; static const int MaxArgs = 100000000;
static const Command CmdPool[Sentinel]; static Command CmdPool[];
class H class H
{ {
public: public:

View File

@ -6,6 +6,7 @@
#include <ctype.h> #include <ctype.h>
#include <iostream> #include <iostream>
#include <sstream>
#include <fstream> #include <fstream>
#include "LogFileSink.h" #include "LogFileSink.h"
#include "ServerPool.h" #include "ServerPool.h"
@ -32,6 +33,15 @@ bool ServerConf::parse(ServerConf& s, const char* str)
return !s.addr.empty(); return !s.addr.empty();
} }
void CustomCommandConf::init(CustomCommandConf&c, const char* name, const int type) {
c.name = name;
c.cmd.type = (Command::Type)type;
c.cmd.name = c.name.c_str();
c.cmd.minArgs = 2;
c.cmd.maxArgs = 2;
c.cmd.mode = Command::Write;
}
Conf::Conf(): Conf::Conf():
mBind("0.0.0.0:7617"), mBind("0.0.0.0:7617"),
mWorkerThreads(1), mWorkerThreads(1),
@ -157,6 +167,8 @@ void Conf::setGlobal(const ConfParser::Node* node)
sentinelServerPool = p; sentinelServerPool = p;
} else if (strcasecmp(p->key.c_str(), "DataCenter") == 0) { } else if (strcasecmp(p->key.c_str(), "DataCenter") == 0) {
dataCenter = p; dataCenter = p;
} else if (strcasecmp(p->key.c_str(), "CustomCommand") == 0) {
setCustomCommand(p);
} else { } else {
Throw(UnknownKey, "%s:%d unknown key %s", p->file, p->line, p->key.c_str()); Throw(UnknownKey, "%s:%d unknown key %s", p->file, p->line, p->key.c_str());
} }
@ -358,6 +370,64 @@ void Conf::setDataCenter(const ConfParser::Node* node)
} }
} }
void Conf::setCustomCommand(const ConfParser::Node* node)
{
if (!node->sub) {
Throw(InvalidValue, "%s:%d CustomCommand require scope value", node->file, node->line);
}
for (auto p = node->sub; p; p = p->next) {
mCustomCommands.push_back(CustomCommandConf{});
auto& cc = mCustomCommands.back();
CustomCommandConf::init(cc, p->key.c_str(), Command::Sentinel);
auto s = p->sub;
if (!s) {
Throw(InvalidValue, "%s:%d CustomCommand.Command require scope value",
node->file, node->line);
}
for (;s ; s = s->next) {
if (setInt(cc.cmd.minArgs, "minArgs", s, 2)) {
} else if (setInt(cc.cmd.maxArgs, "maxArgs", s, 2, 9999)) {
} else if (setCommandMode(cc.cmd.mode, "mode", s)) {
} else {
Throw(UnknownKey, "%s:%d unknown key %s",
s->file, s->line, s->key.c_str());
}
}
Command::addCustomCommand(&cc.cmd);
}
}
bool Conf::setCommandMode(int& mode, const char* name, const ConfParser::Node* n, const int defaultMode)
{
if (strcasecmp(name, n->key.c_str()) == 0) {
if (n->val.size() == 0) {
mode = defaultMode;
} else {
mode = Command::Unknown;
}
std::string mask;
std::istringstream is(n->val);
while (std::getline(is, mask, ',')) {
if ((strcasecmp(mask.c_str(), "Write") == 0)) {
mode |= Command::Write;
} else if ((strcasecmp(mask.c_str(), "Read") == 0)) {
mode |= Command::Read;
} else if ((strcasecmp(mask.c_str(), "Admin") == 0)) {
mode |= Command::Admin;
} else if ((strcasecmp(mask.c_str(), "KeyAt2") == 0)) {
mode |= Command::KeyAt2;
} else if ((strcasecmp(mask.c_str(), "KeyAt3") == 0)) {
mode |= Command::KeyAt3;
} else {
Throw(InvalidValue, "%s:%d %s %s is not an mode",
n->file, n->line, name, n->val.c_str());
}
}
return true;
}
return false;
}
void Conf::setDC(DCConf& dc, const ConfParser::Node* node) void Conf::setDC(DCConf& dc, const ConfParser::Node* node)
{ {
if (!node->sub) { if (!node->sub) {

View File

@ -19,6 +19,7 @@
#include "Distribution.h" #include "Distribution.h"
#include "ConfParser.h" #include "ConfParser.h"
#include "Auth.h" #include "Auth.h"
#include "Command.h"
struct AuthConf struct AuthConf
{ {
@ -89,10 +90,18 @@ struct DCConf
struct LatencyMonitorConf struct LatencyMonitorConf
{ {
std::string name; std::string name;
std::bitset<Command::Sentinel> cmds; std::bitset<Command::AvailableCommands> cmds;
std::vector<long> timeSpan;//us std::vector<long> timeSpan;//us
}; };
struct CustomCommandConf
{
std::string name;
Command cmd;
static void init(CustomCommandConf &c, const char* name, const int type);
};
class Conf class Conf
{ {
public: public:
@ -201,6 +210,8 @@ private:
void setDC(DCConf& dc, const ConfParser::Node* n); void setDC(DCConf& dc, const ConfParser::Node* n);
void setReadPolicy(ReadPolicyConf& c, const ConfParser::Node* n); void setReadPolicy(ReadPolicyConf& c, const ConfParser::Node* n);
void setLatencyMonitor(LatencyMonitorConf& m, const ConfParser::Node* n); void setLatencyMonitor(LatencyMonitorConf& m, const ConfParser::Node* n);
void setCustomCommand(const ConfParser::Node* n);
bool setCommandMode(int& mode, const char* name, const ConfParser::Node* n, const int defaultMode = Command::Write);
private: private:
std::string mName; std::string mName;
std::string mBind; std::string mBind;
@ -220,6 +231,7 @@ private:
std::vector<DCConf> mDCConfs; std::vector<DCConf> mDCConfs;
std::string mLocalDC; std::string mLocalDC;
std::vector<LatencyMonitorConf> mLatencyMonitors; std::vector<LatencyMonitorConf> mLatencyMonitors;
std::vector<CustomCommandConf> mCustomCommands;
}; };

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;
}; };