mirror of
https://github.com/joyieldInc/predixy.git
synced 2025-12-24 22:46:41 +08:00
Merge a0a9d818df into ce210cdee3
This commit is contained in:
commit
22bc20f82e
66
conf/command.conf
Normal file
66
conf/command.conf
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
|||||||
@ -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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
70
src/Conf.cpp
70
src/Conf.cpp
@ -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) {
|
||||||
|
|||||||
14
src/Conf.h
14
src/Conf.h
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user