mirror of
https://github.com/joyieldInc/predixy.git
synced 2025-12-24 22:46:41 +08:00
Add support custom commands
Custom commands are from redis module can be added up to 16(currently).
Configuration is like below.
CustomCommand {
hello { # hello is command, must be lower case.
# this command has 2 or 3 parameters and first argument is key
minArgs 2 # minimum arguments(including command itself)
maxArgs 3 # maximum arguments(including command itself)
mode Write,Read # this command is writable and readable
# mode value can be Admin, Private, NoKey, MultiKey, SMultiKey, MultiKeyVal, KeyAt2, KeyAt3
}
newcommand { # default minArgs = 1, maxArgs = 1 and mode = Write
mode Admin
}
...
}
This commit is contained in:
parent
ce210cdee3
commit
5d9cd99270
@ -10,7 +10,7 @@
|
||||
#include "String.h"
|
||||
#include "Command.h"
|
||||
|
||||
const Command Command::CmdPool[Sentinel] = {
|
||||
Command Command::CmdPool[AvailableCommands] = {
|
||||
{None, "", 0, MaxArgs, Read},
|
||||
{Ping, "ping", 1, 2, Read},
|
||||
{PingServ, "ping", 1, 2, Inner},
|
||||
@ -171,11 +171,14 @@ const Command Command::CmdPool[Sentinel] = {
|
||||
{SubMsg, "\000SubMsg", 0, 0, Admin}
|
||||
};
|
||||
|
||||
int Command::Sentinel = Command::MaxCommands;
|
||||
Command::CommandMap Command::CmdMap;
|
||||
|
||||
void Command::init()
|
||||
{
|
||||
int type = 0;
|
||||
for (auto& i : CmdPool) {
|
||||
for (auto j = 0; j < MaxCommands; j++) {
|
||||
const auto& i = CmdPool[j];
|
||||
if (i.type != type) {
|
||||
Throw(InitFail, "command %s unmatch the index in commands table", i.name);
|
||||
}
|
||||
@ -187,3 +190,12 @@ void Command::init()
|
||||
}
|
||||
}
|
||||
|
||||
void Command::addCustomCommand(const Command *p) {
|
||||
if (nullptr != find(p->name)) {
|
||||
Throw(InitFail, "custom command %s is duplicated", p->name);
|
||||
}
|
||||
CmdPool[Sentinel] = *p;
|
||||
CmdMap[p->name] = &CmdPool[Sentinel];
|
||||
Sentinel++;
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#define _PREDIXY_COMMAND_H_
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "Exception.h"
|
||||
#include "HashFunc.h"
|
||||
|
||||
@ -189,7 +190,8 @@ public:
|
||||
Unsubscribe,
|
||||
SubMsg,
|
||||
|
||||
Sentinel
|
||||
MaxCommands,
|
||||
AvailableCommands = MaxCommands + 128,
|
||||
};
|
||||
enum Mode
|
||||
{
|
||||
@ -242,6 +244,7 @@ public:
|
||||
if (cursor < Sentinel) {
|
||||
return &CmdPool[cursor++];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
static const Command* find(const String& cmd)
|
||||
@ -249,9 +252,11 @@ public:
|
||||
auto it = CmdMap.find(cmd);
|
||||
return it == CmdMap.end() ? nullptr : it->second;
|
||||
}
|
||||
static void addCustomCommand(const Command *pc);
|
||||
static int Sentinel;
|
||||
private:
|
||||
static const int MaxArgs = 100000000;
|
||||
static const Command CmdPool[Sentinel];
|
||||
static Command CmdPool[];
|
||||
class H
|
||||
{
|
||||
public:
|
||||
|
||||
79
src/Conf.cpp
79
src/Conf.cpp
@ -6,6 +6,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include "LogFileSink.h"
|
||||
#include "ServerPool.h"
|
||||
@ -32,6 +33,15 @@ bool ServerConf::parse(ServerConf& s, const char* str)
|
||||
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 = 1;
|
||||
c.cmd.maxArgs = 1;
|
||||
c.cmd.mode = Command::Write;
|
||||
}
|
||||
|
||||
Conf::Conf():
|
||||
mBind("0.0.0.0:7617"),
|
||||
mWorkerThreads(1),
|
||||
@ -157,6 +167,8 @@ void Conf::setGlobal(const ConfParser::Node* node)
|
||||
sentinelServerPool = p;
|
||||
} else if (strcasecmp(p->key.c_str(), "DataCenter") == 0) {
|
||||
dataCenter = p;
|
||||
} else if (strcasecmp(p->key.c_str(), "CustomCommand") == 0) {
|
||||
setCustomCommand(p);
|
||||
} else {
|
||||
Throw(UnknownKey, "%s:%d unknown key %s", p->file, p->line, p->key.c_str());
|
||||
}
|
||||
@ -358,6 +370,73 @@ 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) {
|
||||
if (Command::Sentinel >= Command::AvailableCommands) {
|
||||
Throw(InvalidValue, "%s:%d Too many custom commands", node->file, node->line);
|
||||
}
|
||||
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) {
|
||||
setInt(cc.cmd.minArgs, "minArgs", s, 1);
|
||||
setInt(cc.cmd.maxArgs, "maxArgs", s, 1, 9999);
|
||||
setCommandMode(cc.cmd.mode, "mode", s);
|
||||
}
|
||||
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(), "Private") == 0)) {
|
||||
mode |= Command::Private;
|
||||
} else if ((strcasecmp(mask.c_str(), "NoKey") == 0)) {
|
||||
mode |= Command::NoKey;
|
||||
} else if ((strcasecmp(mask.c_str(), "MultiKey") == 0)) {
|
||||
mode |= Command::MultiKey;
|
||||
} else if ((strcasecmp(mask.c_str(), "SMultiKey") == 0)) {
|
||||
mode |= Command::SMultiKey;
|
||||
} else if ((strcasecmp(mask.c_str(), "MultiKeyVal") == 0)) {
|
||||
mode |= Command::MultiKeyVal;
|
||||
} 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)
|
||||
{
|
||||
if (!node->sub) {
|
||||
|
||||
14
src/Conf.h
14
src/Conf.h
@ -19,6 +19,7 @@
|
||||
#include "Distribution.h"
|
||||
#include "ConfParser.h"
|
||||
#include "Auth.h"
|
||||
#include "Command.h"
|
||||
|
||||
struct AuthConf
|
||||
{
|
||||
@ -89,10 +90,18 @@ struct DCConf
|
||||
struct LatencyMonitorConf
|
||||
{
|
||||
std::string name;
|
||||
std::bitset<Command::Sentinel> cmds;
|
||||
std::bitset<Command::AvailableCommands> cmds;
|
||||
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
|
||||
{
|
||||
public:
|
||||
@ -201,6 +210,8 @@ private:
|
||||
void setDC(DCConf& dc, const ConfParser::Node* n);
|
||||
void setReadPolicy(ReadPolicyConf& c, 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:
|
||||
std::string mName;
|
||||
std::string mBind;
|
||||
@ -220,6 +231,7 @@ private:
|
||||
std::vector<DCConf> mDCConfs;
|
||||
std::string mLocalDC;
|
||||
std::vector<LatencyMonitorConf> mLatencyMonitors;
|
||||
std::vector<CustomCommandConf> mCustomCommands;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -98,7 +98,7 @@ public:
|
||||
Buffer* output(Buffer* buf) const;
|
||||
private:
|
||||
String mName;
|
||||
const std::bitset<Command::Sentinel>* mCmds;
|
||||
const std::bitset<Command::AvailableCommands>* mCmds;
|
||||
std::vector<TimeSpan> mTimeSpan;
|
||||
TimeSpan mLast;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user