acl/app/redis_tools/redis_builder/redis_commands.cpp

1592 lines
36 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "redis_util.h"
#include "redis_status.h"
#include "redis_commands.h"
#ifdef HAS_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
#define LIMIT 40
2016-04-15 14:51:45 +08:00
static const REDIS_CMD __redis_cmds[] =
{
2016-08-27 18:34:02 +08:00
{ "ALL", "none", "yes" },
{ "BGREWRITEAOF", "all", "yes" },
{ "BGSAVE", "all", "yes" },
{ "CONFIG", "all", "yes" },
{ "DBSIZE", "master", "yes" },
{ "FLUSHALL", "master", "yes" },
{ "FLUSHDB", "master", "yes" },
{ "LASTSAVE", "all", "yes" },
{ "MONITOR", "master", "yes" },
{ "PSYNC", "all", "yes" },
{ "SAVE", "all", "yes" },
{ "SHUTDOWN", "all", "yes" },
{ "SLOWLOG", "all", "yes" },
{ "SYNC", "all", "yes" },
{ "TIME", "all", "yes" },
{ "KEYS", "master", "yes" },
{ "SCAN", "master", "yes" },
{ "", "none", "no" },
2016-04-15 14:51:45 +08:00
};
redis_commands::redis_commands(const char* addr, const char* passwd,
2016-04-15 14:51:45 +08:00
int conn_timeout, int rw_timeout, bool prefer_master,
const char* cmds_file)
2019-06-17 10:51:28 +08:00
: conn_timeout_(conn_timeout)
, rw_timeout_(rw_timeout)
, prefer_master_(prefer_master)
, all_cmds_perm_("yes")
{
2019-06-17 10:51:28 +08:00
if (passwd && *passwd) {
passwd_ = passwd;
2019-06-17 10:51:28 +08:00
}
set_addr(addr, addr_);
conns_ = NULL;
2016-04-15 14:51:45 +08:00
init(cmds_file);
create_cluster();
}
redis_commands::~redis_commands(void)
{
delete conns_;
pipeline_->stop_thread();
delete pipeline_;
}
2016-04-15 14:51:45 +08:00
void redis_commands::init(const char* cmds_file)
{
set_commands();
2016-04-16 12:25:41 +08:00
2019-06-17 10:51:28 +08:00
if (cmds_file && *cmds_file) {
2016-04-15 14:51:45 +08:00
acl::ifstream in;
2019-06-17 10:51:28 +08:00
if (!in.open_read(cmds_file)) {
2016-04-16 12:25:41 +08:00
logger_error("load file %s error: %s",
cmds_file, acl::last_serror());
2016-04-15 14:51:45 +08:00
return;
}
load_commands(in);
}
show_commands();
}
void redis_commands::set_commands(void)
{
2019-06-17 10:51:28 +08:00
for (size_t i = 0; !__redis_cmds[i].cmd.empty(); i++) {
2016-04-15 14:51:45 +08:00
acl::string cmd(__redis_cmds[i].cmd);
2017-06-18 18:32:19 +08:00
cmd.upper();
2016-04-15 14:51:45 +08:00
std::map<acl::string, REDIS_CMD>::const_iterator cit =
redis_cmds_.find(cmd);
2019-06-17 10:51:28 +08:00
if (cit != redis_cmds_.end()) {
2016-04-15 14:51:45 +08:00
continue;
2019-06-17 10:51:28 +08:00
}
2016-04-15 14:51:45 +08:00
redis_cmds_[cmd] = __redis_cmds[i];
}
}
void redis_commands::load_commands(acl::istream& in)
{
acl::string line;
size_t i = 0;
2019-06-17 10:51:28 +08:00
while (!in.eof()) {
if (!in.gets(line)) {
2016-04-15 14:51:45 +08:00
break;
2019-06-17 10:51:28 +08:00
}
2016-04-15 14:51:45 +08:00
i++;
line.trim_left_space().trim_right_space();
2019-06-17 10:51:28 +08:00
if (line.empty() || line[0] == '#') {
2016-04-15 14:51:45 +08:00
continue;
2019-06-17 10:51:28 +08:00
}
2016-04-15 14:51:45 +08:00
add_cmdline(line, i);
}
}
void redis_commands::add_cmdline(acl::string& line, size_t i)
{
std::vector<acl::string>& tokens = line.split2(" \t|:,;");
2019-06-17 10:51:28 +08:00
if (tokens.size() < 3) {
2016-04-15 14:51:45 +08:00
logger_warn("skip line(%d): %s", (int) i, line.c_str());
return;
}
acl::string cmd(tokens[0]);
cmd.upper();
2016-04-16 12:25:41 +08:00
2019-06-17 10:51:28 +08:00
if (cmd == "ALL") {
2016-04-16 12:25:41 +08:00
all_cmds_perm_ = tokens[2];
all_cmds_perm_.lower();
2019-06-17 10:51:28 +08:00
if (all_cmds_perm_ == "warn" || all_cmds_perm_ == "no") {
2016-04-16 12:25:41 +08:00
return;
2019-06-17 10:51:28 +08:00
}
2016-04-15 14:51:45 +08:00
return;
}
REDIS_CMD redis_cmd;
redis_cmd.cmd = cmd;
2016-08-27 18:34:02 +08:00
redis_cmd.broadcast = tokens[1].lower();
2016-04-16 12:25:41 +08:00
redis_cmd.perm = tokens[2];
redis_cmd.perm.lower();
2019-06-17 10:51:28 +08:00
if (redis_cmd.perm != "yes" && redis_cmd.perm != "warn") {
2016-04-16 12:25:41 +08:00
redis_cmd.perm = "no";
2019-06-17 10:51:28 +08:00
}
2016-04-15 14:51:45 +08:00
redis_cmds_[cmd] = redis_cmd;
}
void redis_commands::show_commands(void)
{
#ifdef ACL_UNIX
printf("\033[1;34;40m%-20s\033[0m"
2016-04-16 12:25:41 +08:00
"\033[1;34;40m%-20s\033[0m"
"\033[1;34;40m%-20s\033[0m\r\n",
2016-04-15 14:51:45 +08:00
#else
2016-04-16 12:25:41 +08:00
printf("%-20s%-20s%-20s\r\n",
2016-04-15 14:51:45 +08:00
#endif
2016-04-16 12:25:41 +08:00
"Command", "Broadcast", "Permission");
2016-04-15 14:51:45 +08:00
for (std::map<acl::string, REDIS_CMD>::const_iterator cit =
2019-06-17 10:51:28 +08:00
redis_cmds_.begin(); cit != redis_cmds_.end(); ++cit) {
2016-04-15 14:51:45 +08:00
#ifdef ACL_UNIX
printf("\033[1;32;40m%-20s\033[0m"
2016-04-16 12:25:41 +08:00
"\033[1;36;40m%-20s\033[0m"
"\033[1;36;40m%-20s\033[0m\r\n",
2016-04-15 14:51:45 +08:00
#else
2016-04-16 12:25:41 +08:00
printf("%-20s%-20s%-20s\r\n",
2016-04-15 14:51:45 +08:00
#endif
cit->second.cmd.c_str(),
2016-08-27 18:34:02 +08:00
cit->second.broadcast.c_str(),
2016-04-16 12:25:41 +08:00
cit->second.perm.c_str());
2016-04-15 14:51:45 +08:00
}
}
void redis_commands::set_addr(const char* in, acl::string& out)
{
2019-06-17 10:51:28 +08:00
if (in == NULL || *in == 0) {
return;
2019-06-17 10:51:28 +08:00
}
acl::string buf(in);
std::vector<acl::string>& tokens = buf.split2(": \t");
2019-06-17 10:51:28 +08:00
if (tokens.size() >= 2) {
out.format("%s:%s", tokens[0].c_str(), tokens[1].c_str());
2019-06-17 10:51:28 +08:00
}
}
void redis_commands::getline(acl::string& buf, const char* prompt /* = NULL */)
{
2019-06-17 10:51:28 +08:00
if (prompt == NULL || *prompt == 0) {
prompt = "redis_builder> ";
2019-06-17 10:51:28 +08:00
}
#ifdef HAS_READLINE
char* ptr = readline(prompt);
2019-06-17 10:51:28 +08:00
if (ptr == NULL) {
exit (0);
2019-06-17 10:51:28 +08:00
}
buf = ptr;
2016-04-30 11:49:41 +08:00
buf.trim_right_line();
2019-06-17 10:51:28 +08:00
if (!buf.empty() && !buf.equal("y", false) && !buf.equal("n", false)) {
2016-04-30 11:49:41 +08:00
add_history(buf.c_str());
2019-06-17 10:51:28 +08:00
}
#else
printf("%s", prompt);
fflush(stdout);
acl::stdin_stream in;
2019-06-17 10:51:28 +08:00
if (!in.gets(buf)) {
exit (0);
2019-06-17 10:51:28 +08:00
}
#endif
}
void redis_commands::create_cluster(void)
{
2019-06-17 10:51:28 +08:00
while (addr_.empty()) {
const char* prompt = "please enter one redis addr: ";
acl::string buf;
getline(buf, prompt);
2019-06-17 10:51:28 +08:00
if (buf.empty()) {
continue;
2019-06-17 10:51:28 +08:00
}
set_addr(buf, addr_);
}
conns_ = new acl::redis_client_cluster;
conns_->set(addr_, conn_timeout_, rw_timeout_);
conns_->set_all_slot(addr_, 0);
pipeline_ = new acl::redis_client_pipeline(addr_);
2019-06-17 10:51:28 +08:00
if (!passwd_.empty()) {
conns_->set_password("default", passwd_);
pipeline_->set_password(passwd_);
2019-06-17 10:51:28 +08:00
}
pipeline_->start_thread();
}
void redis_commands::help(void)
{
#ifdef ACL_UNIX
printf("> \033[1;33;40mkeys\033[0m"
" \033[1;36;40mpattern limit\033[0m\r\n");
2016-04-30 11:49:41 +08:00
printf("> \033[1;33;40mscan\033[0m"
" \033[1;36;40mpattern display_count ip:port\033[0m\r\n");
printf("> \033[1;33;40mget\033[0m"
" \033[1;36;40m[:limit] parameter ...\033[0m\r\n");
printf("> \033[1;33;40mgetn\033[0m"
" \033[1;36;40mparameter limit\033[0m\r\n");
printf("> \033[1;33;40mremove\033[0m"
2019-03-28 11:35:19 +08:00
" \033[1;36;40mpattern cocurrent\033[0m\r\n");
printf("> \033[1;33;40mtype\033[0m"
" \033[1;36;40mparameter ...\033[0m\r\n");
printf("> \033[1;33;40mttl\033[0m"
" \033[1;36;40mparameter ...\033[0m\r\n");
printf("> \033[1;33;40mserver\033[0m"
" \033[1;36;40mredis_addr\033[0m\r\n");
printf("> \033[1;33;40mdbsize\033[0m\r\n");
printf("> \033[1;33;40mnodes\033[0m\r\n");
2016-04-14 22:39:11 +08:00
printf("> \033[1;33;40mconfig set|get parameter\033[0m\r\n");
printf("> \033[1;33;40mconfig rewrite\033[0m\r\n");
printf("> \033[1;33;40mconfig resetstat\033[0m\r\n");
#else
printf("> keys pattern limit\r\n");
2016-04-30 11:49:41 +08:00
printf("> scan pattern display_count ip:port\r\n");
printf("> get [:limit] parameter ...\r\n");
printf("> getn parameter limit\r\n");
2019-03-28 11:35:19 +08:00
printf("> remove pattern cocurrent\r\n");
printf("> type parameter ...\r\n");
printf("> ttl parameter ...\r\n");
printf("> server redis_addr\r\n");
printf("> dbsize\r\n");
printf("> nodes\r\n");
2016-04-14 22:39:11 +08:00
printf("> config set|get parameter\r\n");
printf("> config rewrite\r\n");
printf("> config resetstat\r\n");
#endif
}
2016-04-15 14:51:45 +08:00
bool redis_commands::check(const char* command)
{
2019-06-17 10:51:28 +08:00
if (all_cmds_perm_ == "no") {
2016-04-16 12:25:41 +08:00
printf("All commands disable!\r\n");
return false;
}
2016-04-15 14:51:45 +08:00
std::map<acl::string, REDIS_CMD>::const_iterator cit =
redis_cmds_.find(command);
2016-08-27 18:34:02 +08:00
acl::string info;
2016-04-16 12:25:41 +08:00
acl::string perm;
2016-04-15 14:51:45 +08:00
2019-06-17 10:51:28 +08:00
if (cit == redis_cmds_.end()) {
2016-08-27 18:34:02 +08:00
info = "BROADCAST";
2016-04-16 12:25:41 +08:00
perm = "yes";
2019-06-17 10:51:28 +08:00
} else {
2016-08-27 18:34:02 +08:00
info = cit->second.broadcast;
2019-06-17 10:51:28 +08:00
if (!info.equal("master", false) && !info.equal("slave", false)) {
2016-08-27 18:34:02 +08:00
info = "SEND";
2019-06-17 10:51:28 +08:00
}
2016-04-16 12:25:41 +08:00
perm = cit->second.perm;
2016-04-15 14:51:45 +08:00
}
2019-06-17 10:51:28 +08:00
if (perm == "no") {
2017-06-20 15:41:04 +08:00
printf("command %s disabled!\r\n", command);
return false;
}
2019-06-17 10:51:28 +08:00
if (all_cmds_perm_ == "warn" || perm == "warn") {
2016-04-15 14:51:45 +08:00
acl::string buf;
acl::string prompt;
prompt.format("Do you want to %s DANGEROUS \"%s\""
" command to all redis nodes ? [y/n]: ",
2016-08-27 18:34:02 +08:00
info.c_str(), command);
2016-04-15 14:51:45 +08:00
getline(buf, prompt);
buf.lower();
2019-06-17 10:51:28 +08:00
if (buf != "y" && buf != "yes") {
2016-04-15 14:51:45 +08:00
printf("You discard \"%s\" command!\r\n", command);
return false;
}
}
return true;
}
2019-06-17 10:51:28 +08:00
bool redis_commands::parse(acl::string& line, std::vector<acl::string>& out)
{
acl::string token, right;
std::vector<acl::string>& tokens = line.split2(" \t", true);
for (std::vector<acl::string>::const_iterator cit = tokens.begin();
cit != tokens.end(); ++cit) {
const acl::string& curr = *cit;
if (!right.empty()) {
if (curr != right) {
token << " " << curr;
} else if (!token.empty()) {
out.push_back(token);
token.clear();
right.clear();
} else {
token.clear();
right.clear();
}
} else if (curr[0] == '\\') {
if (curr.size() >= 2) {
token << " " << curr.c_str() + 1;
} else {
token << '\\';
}
} else if (curr == "\'" || curr == "\"") {
right = curr;
} else {
out.push_back(curr);
}
}
return !out.empty();
}
void redis_commands::run(void)
{
acl::string buf;
2019-06-17 10:51:28 +08:00
while (true) {
getline(buf);
if (buf.equal("quit", false) || buf.equal("exit", false)
2019-06-17 10:51:28 +08:00
|| buf.equal("q", false)) {
printf("Bye!\r\n");
break;
}
if (buf.empty() || buf.equal("help", false)
2019-06-17 10:51:28 +08:00
|| buf.equal("h", false)) {
help();
continue;
}
2019-06-17 10:51:28 +08:00
std::vector<acl::string> tokens;
if (!parse(buf, tokens)) {
continue;
}
acl::string& cmd = tokens[0];
2016-04-15 14:51:45 +08:00
cmd.upper();
2019-06-17 10:51:28 +08:00
if (!check(cmd)) {
2016-04-15 14:51:45 +08:00
continue;
2019-06-17 10:51:28 +08:00
}
2019-06-17 10:51:28 +08:00
if (cmd == "DATE") {
show_date();
2019-06-17 10:51:28 +08:00
} else if (cmd == "SERVER") {
set_server(tokens);
2019-06-17 10:51:28 +08:00
} else if (cmd == "NODES") {
show_nodes();
2019-06-17 10:51:28 +08:00
} else if (cmd == "KEYS") {
get_keys(tokens);
2019-06-17 10:51:28 +08:00
} else if (cmd == "SCAN") {
2016-04-30 11:49:41 +08:00
scan_keys(tokens);
2019-06-17 10:51:28 +08:00
} else if (cmd == "GET") {
get(tokens);
2019-06-17 10:51:28 +08:00
} else if (cmd == "GETN") {
getn(tokens);
2019-06-17 10:51:28 +08:00
} else if (cmd == "REMOVE" || cmd == "RM") {
pattern_remove(tokens);
2019-06-17 10:51:28 +08:00
} else if (cmd == "TYPE") {
check_type(tokens);
2019-06-17 10:51:28 +08:00
} else if (cmd == "TTL") {
check_ttl(tokens);
2019-06-17 10:51:28 +08:00
} else if (cmd == "DBSIZE") {
get_dbsize(tokens);
2019-06-17 10:51:28 +08:00
} else if (cmd == "CONFIG") {
2016-04-14 22:39:11 +08:00
config(tokens);
2019-06-17 10:51:28 +08:00
}
#ifdef HAS_READLINE
2019-06-17 10:51:28 +08:00
else if (cmd == "CLEAR" || cmd == "CL") {
rl_clear_screen(0, 0);
printf("\r\n");
}
#endif
2019-06-17 10:51:28 +08:00
else {
request(tokens);
2019-06-17 10:51:28 +08:00
}
}
}
void redis_commands::set_server(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.size() < 2) {
printf("> usage: server ip:port\r\n");
return;
}
acl::string buf(tokens[1]);
2019-06-17 10:51:28 +08:00
if (tokens.size() >= 3) {
buf << " " << tokens[2];
2019-06-17 10:51:28 +08:00
}
acl::string addr;
set_addr(buf, addr);
2019-06-17 10:51:28 +08:00
if (addr_ == addr) {
printf("no change, redis server addr: %s\r\n", addr_.c_str());
return;
}
printf("set redis server addr from %s to %s\r\n",
addr_.c_str(), addr.c_str());
addr_ = addr;
delete conns_;
create_cluster();
}
void redis_commands::show_nodes(void)
{
acl::redis_client client(addr_, conn_timeout_, rw_timeout_);
client.set_password(passwd_);
acl::redis redis(&client);
redis_status status(addr_, conn_timeout_, rw_timeout_, passwd_);
status.show_nodes(redis);
}
void redis_commands::show_date(void)
{
char buf[256];
acl::rfc822 rfc;
rfc.mkdate_cst(time(NULL), buf, sizeof(buf));
printf("Date: %s\r\n", buf);
}
void redis_commands::get_keys(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.size() < 2) {
printf("> usage: keys parameter\r\n");
return;
}
const char* pattern = tokens[1].c_str();
int max;
2019-06-17 10:51:28 +08:00
if (tokens.size() >= 3) {
max = atoi(tokens[2].c_str());
2019-06-17 10:51:28 +08:00
if (max < 0) {
max = 10;
2019-06-17 10:51:28 +08:00
}
} else {
max = 10;
2019-06-17 10:51:28 +08:00
}
acl::redis redis(conns_);
std::vector<acl::redis_node*> nodes;
redis_util::get_nodes(redis, prefer_master_, nodes);
int n = 0;
2019-06-17 10:51:28 +08:00
if (!nodes.empty()) {
for (std::vector<acl::redis_node*>::const_iterator
2019-06-17 10:51:28 +08:00
cit = nodes.begin(); cit != nodes.end(); ++cit) {
n += get_keys((*cit)->get_addr(), pattern, max);
}
2019-06-17 10:51:28 +08:00
} else {
n += get_keys(addr_, pattern, max);
2019-06-17 10:51:28 +08:00
}
printf("-----keys %s: total count: %d----\r\n", tokens[1].c_str(), n);
}
int redis_commands::get_keys(const char* addr, const char* pattern, int max)
{
2019-06-17 10:51:28 +08:00
if (addr == NULL || *addr == 0) {
printf("addr NULL\r\nEnter any key to continue ...\r\n");
getchar();
return 0;
}
acl::redis_client conn(addr, conn_timeout_, rw_timeout_);
conn.set_password(passwd_);
std::vector<acl::string> res;
acl::redis_key redis(&conn);
2019-06-17 10:51:28 +08:00
if (redis.keys_pattern(pattern, &res) <= 0) {
return 0;
2019-06-17 10:51:28 +08:00
}
int n = 0;
for (std::vector<acl::string>::const_iterator cit = res.begin();
2019-06-17 10:51:28 +08:00
cit != res.end(); ++cit) {
printf("%s\r\n", (*cit).c_str());
n++;
2019-06-17 10:51:28 +08:00
if (n >= max) {
break;
2019-06-17 10:51:28 +08:00
}
}
printf("--- Addr: %s, Total: %d, Limit: %d, Show: %d ---\r\n",
addr, (int) res.size(), max, n);
return (int) res.size();
}
2016-04-30 11:49:41 +08:00
void redis_commands::scan_keys(const std::vector<acl::string>& tokens)
{
const char* pattern = NULL;
size_t display_count = 10;
acl::string addr;
size_t size = tokens.size();
2019-06-17 10:51:28 +08:00
if (size >= 2) {
2016-04-30 11:49:41 +08:00
pattern = tokens[1].c_str();
2019-06-17 10:51:28 +08:00
} else {
2016-04-30 11:49:41 +08:00
pattern = "*";
2019-06-17 10:51:28 +08:00
}
2016-04-30 11:49:41 +08:00
2019-06-17 10:51:28 +08:00
if (size >= 3) {
2016-04-30 11:49:41 +08:00
display_count = (size_t) atoi(tokens[2].c_str());
2019-06-17 10:51:28 +08:00
}
if (size >= 4) {
2016-04-30 11:49:41 +08:00
addr = tokens[3];
2019-06-17 10:51:28 +08:00
}
2016-04-30 11:49:41 +08:00
2019-06-17 10:51:28 +08:00
if (!addr.empty()) {
2016-04-30 11:49:41 +08:00
scan(addr, pattern, display_count);
return;
}
acl::redis redis(conns_);
std::vector<acl::redis_node*> nodes;
redis_util::get_nodes(redis, prefer_master_, nodes);
int total = 0;
for (std::vector<acl::redis_node*>::const_iterator cit
2019-06-17 10:51:28 +08:00
= nodes.begin(); cit != nodes.end();) {
2016-04-30 11:49:41 +08:00
int n = scan((*cit)->get_addr(), pattern, display_count);
2019-06-17 10:51:28 +08:00
if (n > 0) {
2016-04-30 11:49:41 +08:00
total += n;
2019-06-17 10:51:28 +08:00
}
2016-04-30 11:49:41 +08:00
printf("There are %d keys in %s.", n, (*cit)->get_addr());
2019-06-17 10:51:28 +08:00
if (++cit == nodes.end()) {
2016-04-30 11:49:41 +08:00
printf("\r\n");
break;
}
acl::string prompt;
prompt.format(" Do you want to scan next %s? [y/n] ",
(*cit)->get_addr());
acl::string buf;
getline(buf, prompt);
2019-06-17 10:51:28 +08:00
if (!buf.empty() && !buf.equal("y", false)) {
2016-04-30 11:49:41 +08:00
break;
2019-06-17 10:51:28 +08:00
}
2016-04-30 11:49:41 +08:00
}
printf("-----scan keys %s: total count: %d----\r\n",
pattern ? pattern : "*", total);
}
int redis_commands::scan(const char* addr, const char* pattern,
size_t display_count)
{
acl::redis_client conn(addr, conn_timeout_, rw_timeout_);
conn.set_password(passwd_);
2016-04-30 11:49:41 +08:00
acl::redis redis(&conn);
size_t count = 10000;
std::vector<acl::string> res;
res.reserve(count);
int cursor = 0, n = 0, i = 0;
size_t n1 = 0;
2019-06-17 10:51:28 +08:00
while (true) {
2016-04-30 11:49:41 +08:00
cursor = redis.scan(cursor, res, pattern, &count);
2019-06-17 10:51:28 +08:00
if (cursor < 0) {
2016-04-30 11:49:41 +08:00
printf("scan error: %s\r\n", redis.result_error());
break;
}
i++;
2022-09-06 15:20:02 +08:00
n += (int) res.size();
2016-04-30 11:49:41 +08:00
2019-06-17 10:51:28 +08:00
if (display_count > 0 && n1++ < display_count) {
2016-04-30 11:49:41 +08:00
size_t n2 = 0;
for (std::vector<acl::string>::const_iterator cit
2019-06-17 10:51:28 +08:00
= res.begin(); cit != res.end(); ++cit) {
if (display_count > 0 && n2 >= display_count) {
2016-04-30 11:49:41 +08:00
break;
2019-06-17 10:51:28 +08:00
}
2022-09-06 15:20:02 +08:00
get((*cit).c_str(), (int) display_count);
2016-04-30 11:49:41 +08:00
n2++;
}
}
2019-06-17 10:51:28 +08:00
if (cursor == 0) {
2016-04-30 11:49:41 +08:00
break;
2019-06-17 10:51:28 +08:00
}
2016-04-30 11:49:41 +08:00
redis.clear();
res.clear();
2019-06-17 10:51:28 +08:00
if (i > 0 && i % 10 == 0) {
2016-04-30 11:49:41 +08:00
acl_doze(100);
2019-06-17 10:51:28 +08:00
}
2016-04-30 11:49:41 +08:00
}
return n;
}
void redis_commands::getn(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.size() < 2) {
printf("> usage: getn key limit\r\n");
return;
}
const char* key = tokens[1].c_str();
int count;
2019-06-17 10:51:28 +08:00
if (tokens.size() >= 3) {
count = atoi(tokens[2].c_str());
2019-06-17 10:51:28 +08:00
if (count < 0) {
count = 10;
2019-06-17 10:51:28 +08:00
}
} else {
count = 10;
2019-06-17 10:51:28 +08:00
}
get(key, count);
}
void redis_commands::get(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.size() < 2) { // xxx
return;
2019-06-17 10:51:28 +08:00
}
std::vector<acl::string>::const_iterator cit = tokens.begin();
++cit;
int max;
const char* ptr = (*cit).c_str();
2019-06-17 10:51:28 +08:00
if (*ptr == ':' && *(ptr + 1) != 0) {
ptr++;
max = atoi(ptr);
2019-06-17 10:51:28 +08:00
if (max < 0) {
max = 10;
2019-06-17 10:51:28 +08:00
}
++cit;
2019-06-17 10:51:28 +08:00
} else {
max = 10;
2019-06-17 10:51:28 +08:00
}
2019-06-17 10:51:28 +08:00
for (; cit != tokens.end(); ++cit) {
const char* key = (*cit).c_str();
get(key, max);
}
}
void redis_commands::get(const char* key, int max)
{
acl::redis cmd(conns_);
acl::redis_key_t type = cmd.type(key);
2019-06-17 10:51:28 +08:00
switch (type) {
case acl::REDIS_KEY_NONE:
break;
case acl::REDIS_KEY_STRING:
string_get(key);
break;
case acl::REDIS_KEY_HASH:
hash_get(key, max);
break;
case acl::REDIS_KEY_LIST:
list_get(key, max);
break;
case acl::REDIS_KEY_SET:
set_get(key, max);
break;
case acl::REDIS_KEY_ZSET:
zset_get(key, max);
break;
default:
printf("%s: unknown type: %d\r\n", key, (int) type);
break;
}
}
void redis_commands::hash_get(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.empty()) { // xxx
return;
2019-06-17 10:51:28 +08:00
}
std::vector<acl::string>::const_iterator cit = tokens.begin();
2019-06-17 10:51:28 +08:00
for (++cit; cit != tokens.end(); ++cit) {
hash_get((*cit).c_str(), 0);
printf("-----------------------------------------------\r\n");
}
}
void redis_commands::hash_get(const char* key, size_t max)
{
std::map<acl::string, acl::string> res;
acl::redis cmd(conns_);
2019-06-17 10:51:28 +08:00
if (!cmd.hgetall(key, res)) {
2016-04-15 14:51:45 +08:00
printf("hgetall error: %s, key: [%s]\r\n",
cmd.result_error(), key);
return;
}
size_t n = 0, count = res.size();
2019-06-17 10:51:28 +08:00
printf("HASH KEY: %s, COUNT: %d, MAX: %d\r\n\r\n",
key, (int) count, (int) max);
for (std::map<acl::string, acl::string>::const_iterator cit2
2019-06-17 10:51:28 +08:00
= res.begin(); cit2 != res.end(); ++cit2) {
2016-04-15 14:51:45 +08:00
printf("[%s]: [%s]\r\n", cit2->first.c_str(),
cit2->second.c_str());
n++;
2019-06-17 10:51:28 +08:00
if (max > 0 && n >= max) {
break;
2019-06-17 10:51:28 +08:00
}
}
2019-06-17 10:51:28 +08:00
printf("\r\nHASH KEY: %s, COUNT: %d, MAX: %d, SHOW: %d\r\n",
key, (int) count, (int) max, (int) n);
}
void redis_commands::string_get(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.empty()) { // xxx
return;
2019-06-17 10:51:28 +08:00
}
std::vector<acl::string>::const_iterator cit = tokens.begin();
2019-06-17 10:51:28 +08:00
for (++cit; cit != tokens.end(); ++cit) {
string_get((*cit).c_str());
printf("-----------------------------------------------\r\n");
}
}
void redis_commands::string_get(const char* key)
{
acl::string buf;
acl::redis cmd(conns_);
2019-06-17 10:51:28 +08:00
if (!cmd.get(key, buf)) {
2016-04-15 14:51:45 +08:00
printf("get error: %s, key: [%s]\r\n", cmd.result_error(), key);
return;
}
2016-04-15 14:51:45 +08:00
printf("STRING KEY: [%s], VALUE: [%s]\r\n", key, buf.c_str());
}
void redis_commands::list_get(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.empty()) { // xxx
return;
2019-06-17 10:51:28 +08:00
}
std::vector<acl::string>::const_iterator cit = tokens.begin();
2019-06-17 10:51:28 +08:00
for (++cit; cit != tokens.end(); ++cit) {
list_get((*cit).c_str(), 0);
printf("-----------------------------------------------\r\n");
}
}
void redis_commands::list_get(const char* key, size_t max)
{
acl::string buf;
acl::redis cmd(conns_);
int len = cmd.llen(key), count = len;
2019-06-17 10:51:28 +08:00
if (len < 0) {
2016-04-15 14:51:45 +08:00
printf("llen error: %s, key: [%s]\r\n",
cmd.result_error(), key);
return;
}
2019-06-17 10:51:28 +08:00
if (len > LIMIT) {
acl::string prompt;
prompt.format("Do you show all %d elements for key %s ? [y/n] ",
len, key);
getline(buf, prompt);
2019-06-17 10:51:28 +08:00
if (!buf.equal("y", false)) {
return;
2019-06-17 10:51:28 +08:00
}
}
2019-06-17 10:51:28 +08:00
if (max > 0 && (size_t) len > max) {
len = (int) max;
2019-06-17 10:51:28 +08:00
}
2016-04-15 14:51:45 +08:00
printf("LIST KEY: [%s], COUNT: %d, MAX: %d, SHOW: %d\r\n",
key, count, (int) max, len);
2019-06-17 10:51:28 +08:00
for (int i = 0; i < len; i++) {
buf.clear();
cmd.clear(false);
2019-06-17 10:51:28 +08:00
if (!cmd.lindex(key, i, buf)) {
printf("lindex error: %s, key: %s, idx: %d\r\n",
cmd.result_error(), key, i);
return;
}
2016-04-15 14:51:45 +08:00
printf("[%s]\r\n", buf.c_str());
}
2016-04-15 14:51:45 +08:00
printf("LIST KEY: [%s], COUNT: %d, MAX: %d, SHOW: %d\r\n",
key, count, (int) max, len);
}
void redis_commands::set_get(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.empty()) { // xxx
return;
2019-06-17 10:51:28 +08:00
}
std::vector<acl::string>::const_iterator cit = tokens.begin();
2019-06-17 10:51:28 +08:00
for (++cit; cit != tokens.end(); ++cit) {
set_get((*cit).c_str(), 0);
printf("-----------------------------------------------\r\n");
}
}
void redis_commands::set_get(const char* key, size_t max)
{
acl::string buf;
acl::redis cmd(conns_);
int len = cmd.scard(key), count = len;
2019-06-17 10:51:28 +08:00
if (len < 0) {
printf("scard error: %s, key: %s\r\n", cmd.result_error(), key);
return;
}
2019-06-17 10:51:28 +08:00
if (len > LIMIT) {
acl::string prompt;
prompt.format("Do you show all %d elements for key %s ? [y/n] ",
len, key);
getline(buf, prompt);
2019-06-17 10:51:28 +08:00
if (!buf.equal("y", false)) {
return;
2019-06-17 10:51:28 +08:00
}
}
2019-06-17 10:51:28 +08:00
if (max > 0 && max > (size_t) len) {
len = (int) max;
2019-06-17 10:51:28 +08:00
}
2016-04-15 14:51:45 +08:00
printf("SET KEY: [%s], COUNT: %d\r\n", key, len);
2019-06-17 10:51:28 +08:00
for (int i = 0; i < len; i++) {
buf.clear();
cmd.clear(false);
2019-06-17 10:51:28 +08:00
if (!cmd.spop(key, buf)) {
2016-04-15 14:51:45 +08:00
printf("spop error: %s, key: [%s], idx: %d\r\n",
cmd.result_error(), key, i);
return;
}
2016-04-15 14:51:45 +08:00
printf("[%s]\r\n", buf.c_str());
}
2016-04-15 14:51:45 +08:00
printf("SET KEY: [%s], COUNT: %d, MAX: %d, SHOW: %d\r\n",
key, count, (int) max, len);
}
void redis_commands::zset_get(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.empty()) { // xxx
return;
2019-06-17 10:51:28 +08:00
}
std::vector<acl::string>::const_iterator cit = tokens.begin();
2019-06-17 10:51:28 +08:00
for (++cit; cit != tokens.end(); ++cit) {
zset_get((*cit).c_str(), 0);
printf("-----------------------------------------------\r\n");
}
}
void redis_commands::zset_get(const char* key, size_t max)
{
acl::string buf;
acl::redis cmd(conns_);
int len = cmd.zcard(key), count = len;
2019-06-17 10:51:28 +08:00
if (len < 0) {
2016-04-15 14:51:45 +08:00
printf("zcard error: %s, key: [%s]\r\n", cmd.result_error(), key);
return;
}
2019-06-17 10:51:28 +08:00
if (len > LIMIT) {
acl::string prompt;
prompt.format("Do you show all %d elements for key %s ? [y/n] ",
len, key);
getline(buf, prompt);
if (!buf.equal("y", false))
return;
}
2019-06-17 10:51:28 +08:00
if (max > 0 && max > (size_t) len) {
len = (int) max;
2019-06-17 10:51:28 +08:00
}
std::vector<acl::string> res;
2016-04-15 14:51:45 +08:00
printf("ZSET KEY: [%s], COUNT: %d, MAX: %d, SHOW: %d\r\n",
key, count, (int) max, len);
2019-06-17 10:51:28 +08:00
for (int i = 0; i < len; i++) {
buf.clear();
cmd.clear(false);
res.clear();
int ret = cmd.zrange(key, i, i + 1, &res);
2019-06-17 10:51:28 +08:00
if (ret < 0) {
2016-04-15 14:51:45 +08:00
printf("zrange error: %s, key: [%s], idx: %d\r\n",
cmd.result_error(), key, i);
return;
}
2019-06-17 10:51:28 +08:00
if (res.empty()) {
continue;
2019-06-17 10:51:28 +08:00
}
for (std::vector<acl::string>::const_iterator cit
2019-06-17 10:51:28 +08:00
= res.begin(); cit != res.end(); ++cit) {
2016-04-15 14:51:45 +08:00
printf("[%s]\r\n", (*cit).c_str());
}
}
2016-04-15 14:51:45 +08:00
printf("ZSET KEY: [%s], COUNT: %d, MAX: %d, SHOW: %d\r\n",
key, count, (int) max, len);
}
void redis_commands::pattern_remove(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.size() < 2) {
printf("> usage: pattern_remove pattern\r\n");
return;
}
acl::log::stdout_open(false);
acl::log::open("redis-builder.log", "remove");
const char* pattern = tokens[1].c_str();
2019-03-28 11:35:19 +08:00
int cocurrent;
2019-06-17 10:51:28 +08:00
if (tokens.size() >= 3) {
2019-03-28 11:35:19 +08:00
cocurrent = atoi(tokens[2]);
2019-06-17 10:51:28 +08:00
} else {
2019-03-28 11:35:19 +08:00
cocurrent = 10;
2019-06-17 10:51:28 +08:00
}
if (cocurrent <= 0) {
2019-03-28 11:35:19 +08:00
cocurrent = 10;
2019-06-17 10:51:28 +08:00
}
2019-03-28 11:35:19 +08:00
acl::redis redis(conns_);
const std::map<acl::string, acl::redis_node*>* masters =
redis_util::get_masters(redis);
long long deleted = 0;
2019-06-17 10:51:28 +08:00
if (masters != NULL) {
for (std::map<acl::string, acl::redis_node*>::const_iterator
2019-06-17 10:51:28 +08:00
cit = masters->begin(); cit != masters->end(); ++cit) {
const char* addr = cit->second->get_addr();
2019-06-17 10:51:28 +08:00
if (addr == NULL || *addr == 0) {
printf("addr NULL, skip it\r\n");
continue;
}
2019-03-28 11:35:19 +08:00
deleted += pattern_remove(addr, pattern, cocurrent);
}
2019-06-17 10:51:28 +08:00
} else {
2019-03-28 11:35:19 +08:00
deleted += pattern_remove(addr_, pattern, cocurrent);
2019-06-17 10:51:28 +08:00
}
acl::log::close();
acl::log::stdout_open(true);
printf("removed pattern: [%s], total: %lld\r\n", pattern, deleted);
}
2019-03-28 11:35:19 +08:00
long long redis_commands::pattern_remove(const char* addr, const char* pattern,
int cocurrent)
{
acl::string buf;
acl::string prompt;
prompt.format("Do you want to delete them all in %s ? [y/n]: ", addr);
getline(buf, prompt);
2019-06-17 10:51:28 +08:00
if (!buf.equal("y", false)) {
return 0;
2019-06-17 10:51:28 +08:00
}
size_t count = 100000;
std::vector<acl::string> res;
res.reserve(count);
acl::redis_client conn(addr, conn_timeout_, rw_timeout_);
2019-06-17 10:51:28 +08:00
if (!passwd_.empty()) {
conn.set_password(passwd_);
2019-06-17 10:51:28 +08:00
}
acl::redis redis(&conn);
acl::atomic_long deleted = 0, error = 0, notfound = 0;
int cursor = 0;
(void) cocurrent;
acl::thread_pool threads;
threads.set_limit((size_t) cocurrent);
threads.start();
2019-06-17 10:51:28 +08:00
while (true) {
size_t keys_count;
cursor = redis.scan(cursor, res, pattern, &count);
2019-06-17 10:51:28 +08:00
if (cursor < 0) {
printf("%s => scan error: %s\r\n",
addr, redis.result_error());
break;
2019-06-17 10:51:28 +08:00
} else if (cursor == 0 && res.empty()) {
printf("%s => scan over\r\n", addr);
break;
}
if (res.empty()) {
continue;
}
keys_count = res.size();
2019-03-28 11:35:19 +08:00
parallel_remove(cocurrent, res, deleted, error, notfound);
//parallel_remove(threads, res, deleted, error, notfound);
//remove(redis, res, deleted, error, notfound);
redis.clear();
res.clear();
printf("%s => deleted: %lld, error: %lld, not found: %lld, "
"count=%zd, keys count=%zd, cursor=%d\r\n",
addr, deleted.value(), error.value(), notfound.value(),
count, keys_count, cursor);
}
threads.stop();
return deleted;
}
void redis_commands::remove(const std::vector<acl::string>& keys,
acl::atomic_long& deleted, acl::atomic_long& error,
acl::atomic_long& notfound)
{
acl::redis cmd(conns_);
int display_count = 0;
for (std::vector<acl::string>::const_iterator cit = keys.begin();
2019-06-17 10:51:28 +08:00
cit != keys.end(); ++cit) {
cmd.clear(false);
int ret = cmd.del_one((*cit).c_str());
display_count++;
2019-06-17 10:51:28 +08:00
if (ret < 0) {
if (display_count < 10) {
printf("del_one error: %s, key: [%s]\r\n",
cmd.result_error(), (*cit).c_str());
2019-06-17 10:51:28 +08:00
}
++error;
2019-06-17 10:51:28 +08:00
} else if (ret == 0) {
if (display_count < 10) {
printf("not exist, key: [%s]\r\n", (*cit).c_str());
2019-06-17 10:51:28 +08:00
}
++notfound;
2019-06-17 10:51:28 +08:00
} else {
if (display_count < 10) {
printf("Delete ok, key: [%s]\r\n", (*cit).c_str());
2019-06-17 10:51:28 +08:00
}
++deleted;
}
}
}
class remove_job : public acl::thread_job
{
public:
remove_job(acl::redis_client_cluster* cluster, const char* key,
acl::atomic_long& deleted, acl::atomic_long& error,
acl::atomic_long& notfound)
: cluster_(cluster)
, pipeline_(NULL)
, key_(key)
, deleted_(deleted)
, error_(error)
, notfound_(notfound)
{
}
remove_job(acl::redis_client_pipeline* pipeline, const char* key,
acl::atomic_long& deleted, acl::atomic_long& error,
acl::atomic_long& notfound)
: cluster_(NULL)
, pipeline_(pipeline)
, key_(key)
, deleted_(deleted)
, error_(error)
, notfound_(notfound)
{
}
private:
~remove_job(void) {}
acl::redis_client_cluster* cluster_;
acl::redis_client_pipeline* pipeline_;
acl::string key_;
acl::atomic_long& deleted_;
acl::atomic_long& error_;
acl::atomic_long& notfound_;
private:
void* run(void)
{
acl::redis cmd;
if (pipeline_) {
cmd.set_pipeline(pipeline_);
} else if (cluster_) {
cmd.set_cluster(cluster_);
} else {
delete this;
return NULL;
}
int ret = cmd.del_one(key_);
if (ret < 0) {
++error_;
} else if (ret == 0) {
++notfound_;
} else {
++deleted_;
}
delete this;
return NULL;
}
};
2019-03-28 11:35:19 +08:00
void redis_commands::parallel_remove(int cocurrent,
const std::vector<acl::string>& keys,
acl::atomic_long& deleted, acl::atomic_long& error,
acl::atomic_long& notfound)
{
acl::thread_pool threads;
2019-03-28 11:35:19 +08:00
threads.set_limit((size_t) cocurrent);
threads.start();
parallel_remove(threads, keys, deleted, error, notfound);
threads.stop();
}
void redis_commands::parallel_remove(acl::thread_pool& threads,
const std::vector<acl::string>& keys,
acl::atomic_long& deleted, acl::atomic_long& error,
acl::atomic_long& notfound)
{
for (std::vector<acl::string>::const_iterator cit = keys.begin();
cit != keys.end(); ++cit) {
#if 0
acl::thread_job* job = new remove_job(conns_, *cit,
deleted, error, notfound);
#else
acl::thread_job* job = new remove_job(pipeline_, *cit,
deleted, error, notfound);
#endif
threads.execute(job);
}
}
void redis_commands::remove(acl::redis& redis,
const std::vector<acl::string>& keys,
acl::atomic_long& deleted, acl::atomic_long& error,
acl::atomic_long& notfound)
{
int ret = redis.del_keys(keys);
if (ret > 0) {
deleted += ret;
} else if (ret == 0) {
notfound++;
} else {
error++;
for (std::vector<acl::string>::const_iterator cit = keys.begin();
cit != keys.end(); ++cit) {
printf(" %s", (*cit).c_str());
}
printf("; del_keys error=%s, keys=%zd\r\n",
redis.result_error(), keys.size());
}
}
void redis_commands::check_type(const std::vector<acl::string>& tokens)
{
acl::redis cmd(conns_);
std::vector<acl::string>::const_iterator cit = tokens.begin();
++cit;
2019-06-17 10:51:28 +08:00
for (; cit != tokens.end(); ++cit) {
cmd.clear(false);
const char* key = (*cit).c_str();
acl::redis_key_t type = cmd.type(key);
2019-06-17 10:51:28 +08:00
switch (type) {
case acl::REDIS_KEY_NONE:
2016-04-15 14:51:45 +08:00
printf("[%s]: NONE\r\n", key);
break;
case acl::REDIS_KEY_STRING:
2016-04-15 14:51:45 +08:00
printf("[%s]: STRING\r\n", key);
break;
case acl::REDIS_KEY_HASH:
2016-04-15 14:51:45 +08:00
printf("[%s]: HASH\r\n", key);
break;
case acl::REDIS_KEY_LIST:
2016-04-15 14:51:45 +08:00
printf("[%s]: LIST\r\n", key);
break;
case acl::REDIS_KEY_SET:
2016-04-15 14:51:45 +08:00
printf("[%s]: SET\r\n", key);
break;
case acl::REDIS_KEY_ZSET:
2016-04-15 14:51:45 +08:00
printf("[%s]: ZSET\r\n", key);
break;
default:
2016-04-15 14:51:45 +08:00
printf("[%s]: UNKNOWN\r\n", key);
break;
}
}
}
void redis_commands::check_ttl(const std::vector<acl::string>& tokens)
{
acl::redis cmd(conns_);
std::vector<acl::string>::const_iterator cit = tokens.begin();
++cit;
2019-06-17 10:51:28 +08:00
for (; cit != tokens.end(); ++cit) {
cmd.clear(false);
const char* key = (*cit).c_str();
int ttl = cmd.ttl(key);
2016-04-15 14:51:45 +08:00
printf("[%s]: %d seconds\r\n", key, ttl);
}
}
void redis_commands::get_dbsize(const std::vector<acl::string>&)
{
acl::redis redis(conns_);
std::vector<acl::redis_node*> nodes;
redis_util::get_nodes(redis, prefer_master_, nodes);
int total = 0;
2019-06-17 10:51:28 +08:00
if (!nodes.empty()) {
for (std::vector<acl::redis_node*>::const_iterator
2019-06-17 10:51:28 +08:00
cit = nodes.begin(); cit != nodes.end(); ++cit) {
const char* addr = (*cit)->get_addr();
2019-06-17 10:51:28 +08:00
if (addr == NULL || *addr == 0) {
printf("addr NULL\r\n");
continue;
}
acl::redis_client conn(addr, conn_timeout_, rw_timeout_);
conn.set_password(passwd_);
acl::redis cmd(&conn);
int n = cmd.dbsize();
2019-06-17 10:57:38 +08:00
printf("\tADDR: %s, DBSIZE: %d\r\n", addr, n);
2019-06-17 10:51:28 +08:00
if (n > 0) {
total += n;
2019-06-17 10:51:28 +08:00
}
}
2019-06-17 10:51:28 +08:00
} else {
acl::redis_client conn(addr_, conn_timeout_, rw_timeout_);
conn.set_password(passwd_);
acl::redis cmd(&conn);
int n = cmd.dbsize();
2019-06-17 10:57:38 +08:00
printf("\tADDR: %s, DBSIZE: %d\r\n", addr_.c_str(), n);
2019-06-17 10:51:28 +08:00
if (n > 0) {
total += n;
2019-06-17 10:51:28 +08:00
}
}
2019-06-17 10:57:38 +08:00
printf("\r\n\tTotal DBSIZE: %d\r\n", total);
}
void redis_commands::request(const std::vector<acl::string>& tokens)
{
2016-04-15 14:51:45 +08:00
acl::string cmd(tokens[0]);
cmd.upper();
std::map<acl::string, REDIS_CMD>::const_iterator cit =
redis_cmds_.find(cmd);
2019-06-17 10:51:28 +08:00
if (cit == redis_cmds_.end()) {
2016-04-15 14:51:45 +08:00
request_one(tokens);
return;
}
2019-06-17 10:51:28 +08:00
if (cit->second.broadcast.equal("all", false)) {
2016-04-15 14:51:45 +08:00
request_all(tokens);
2019-06-17 10:51:28 +08:00
} else if (cit->second.broadcast.equal("master", false)) {
2016-08-27 18:34:02 +08:00
request_masters(tokens);
2019-06-17 10:51:28 +08:00
} else if (cit->second.broadcast.equal("slave", false)) {
2016-08-27 18:34:02 +08:00
request_slaves(tokens);
2019-06-17 10:51:28 +08:00
} else {
2016-04-15 14:51:45 +08:00
request_one(tokens);
2019-06-17 10:51:28 +08:00
}
2016-04-15 14:51:45 +08:00
}
void redis_commands::request_one(const std::vector<acl::string>& tokens)
{
acl::redis redis(conns_);
const acl::redis_result* result = redis.request(tokens);
2019-06-17 10:51:28 +08:00
if (result == NULL) {
2016-04-15 14:51:45 +08:00
printf("request error: %s, addr: %s\r\n",
redis.result_error(), redis.get_client_addr());
2016-04-14 22:39:11 +08:00
show_request(tokens);
printf("\r\n");
return;
}
2016-04-15 14:51:45 +08:00
show_result(*result, redis.get_client_addr());
}
void redis_commands::request_all(const std::vector<acl::string>& tokens)
{
acl::redis_client client(addr_, conn_timeout_, rw_timeout_);
client.set_password(passwd_);
acl::redis redis(&client);
std::vector<const acl::redis_node*> nodes;
redis_util::get_all_nodes(redis, nodes);
2019-06-17 10:51:28 +08:00
if (nodes.empty()) {
2016-04-15 14:51:45 +08:00
logger_error("no node of the cluster: %s", addr_.c_str());
return;
}
for (std::vector<const acl::redis_node*>::const_iterator cit
2019-06-17 10:51:28 +08:00
= nodes.begin(); cit != nodes.end(); ++cit) {
2016-04-15 14:51:45 +08:00
const char* addr = (*cit)->get_addr();
2019-06-17 10:51:28 +08:00
if (addr == NULL || *addr == 0) {
2016-04-15 14:51:45 +08:00
logger_error("addr NULL");
continue;
}
request_one(addr, tokens);
}
}
2016-08-27 18:34:02 +08:00
void redis_commands::request_masters(const std::vector<acl::string>& tokens)
{
acl::redis redis(conns_);
const std::map<acl::string, acl::redis_node*>* masters =
redis_util::get_masters(redis);
2019-06-17 10:51:28 +08:00
if (masters == NULL) {
2016-08-27 18:34:02 +08:00
logger_error("no masters node of the cluster");
return;
}
for (std::map<acl::string, acl::redis_node*>::const_iterator cit
2019-06-17 10:51:28 +08:00
= masters->begin(); cit != masters->end(); ++cit) {
2016-08-27 18:34:02 +08:00
const char* addr = cit->second->get_addr();
2019-06-17 10:51:28 +08:00
if (addr == NULL || *addr == 0) {
2016-08-27 18:34:02 +08:00
logger_error("addr NULL");
continue;
}
request_one(addr, tokens);
}
}
void redis_commands::request_slaves(const std::vector<acl::string>& tokens)
{
acl::redis redis(conns_);
std::vector<const acl::redis_node*> slaves;
redis_util::get_slaves(redis, slaves);
2019-06-17 10:51:28 +08:00
if (slaves.empty()) {
2016-08-27 18:34:02 +08:00
logger_error("no slaves node of the cluster");
return;
}
for (std::vector<const acl::redis_node*>::const_iterator cit
2019-06-17 10:51:28 +08:00
= slaves.begin(); cit != slaves.end(); ++cit) {
2016-08-27 18:34:02 +08:00
const char* addr = (*cit)->get_addr();
2019-06-17 10:51:28 +08:00
if (addr == NULL || *addr == 0) {
2016-08-27 18:34:02 +08:00
logger_error("addr NULL");
continue;
}
request_one(addr, tokens);
}
}
2016-04-14 23:39:09 +08:00
bool redis_commands::show_result(const acl::redis_result& result,
const char* addr)
{
acl::string buf;
size_t size;
const acl::redis_result** children;
acl::redis_result_t type = result.get_type();
2019-06-17 10:51:28 +08:00
switch (type) {
case acl::REDIS_RESULT_NIL:
2019-06-17 10:51:28 +08:00
if (addr && *addr) {
2016-04-14 23:39:09 +08:00
printf("%s-->", addr);
2019-06-17 10:51:28 +08:00
}
printf("[nil]\r\n");
break;
case acl::REDIS_RESULT_ERROR:
2019-06-17 10:51:28 +08:00
if (addr && *addr) {
2016-04-14 23:39:09 +08:00
printf("%s-->", addr);
2019-06-17 10:51:28 +08:00
}
printf("-%s\r\n", result.get_error());
2016-04-14 22:39:11 +08:00
return false;
case acl::REDIS_RESULT_STATUS:
2019-06-17 10:51:28 +08:00
if (addr && *addr) {
2016-04-14 23:39:09 +08:00
printf("%s-->", addr);
2019-06-17 10:51:28 +08:00
}
printf("+%s\r\n", result.get_status());
break;
case acl::REDIS_RESULT_INTEGER:
2019-06-17 10:51:28 +08:00
if (addr && *addr) {
2016-04-14 23:39:09 +08:00
printf("%s-->", addr);
2019-06-17 10:51:28 +08:00
}
printf(":%lld\r\n", result.get_integer64());
break;
case acl::REDIS_RESULT_STRING:
buf.clear();
result.argv_to_string(buf);
2019-06-17 10:51:28 +08:00
if (!buf.empty()) {
printf("$%d\r\n%s\r\n", (int) buf.size(), buf.c_str());
2019-06-17 10:51:28 +08:00
}
break;
case acl::REDIS_RESULT_ARRAY:
children = result.get_children(&size);
2019-06-17 10:51:28 +08:00
if (size > 0) {
printf("*%d\r\n", (int) size);
2019-06-17 10:51:28 +08:00
}
for (size_t i = 0; i < size; i++) {
const acl::redis_result* rr = children[i];
acl_assert(rr != NULL);
2016-04-14 23:39:09 +08:00
show_result(*rr, addr);
}
break;
case acl::REDIS_RESULT_UNKOWN:
default:
2019-06-17 10:51:28 +08:00
if (addr && *addr) {
2016-04-14 23:39:09 +08:00
printf("%s-->", addr);
2019-06-17 10:51:28 +08:00
}
printf("unknown type: %d\r\n", (int) type);
2016-04-14 22:39:11 +08:00
return false;
}
return true;
}
void redis_commands::show_request(const std::vector<acl::string>& tokens)
{
for (std::vector<acl::string>::const_iterator cit =
2019-06-17 10:51:28 +08:00
tokens.begin(); cit != tokens.end(); ++cit) {
if (cit == tokens.begin()) {
2016-04-14 22:39:11 +08:00
printf("%s", (*cit).c_str());
2019-06-17 10:51:28 +08:00
} else {
2016-04-14 22:39:11 +08:00
printf(" \"%s\"", (*cit).c_str());
2019-06-17 10:51:28 +08:00
}
}
}
2016-04-14 22:39:11 +08:00
void redis_commands::config_usage(void)
{
logger_error("> usage: config get parameter");
logger_error("> usage: config set parameter");
logger_error("> usage: config rewrite");
logger_error("> usage: config resetstat");
}
void redis_commands::config(const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.size() < 2) {
2016-04-14 22:39:11 +08:00
config_usage();
return;
}
acl::redis_client client(addr_, conn_timeout_, rw_timeout_);
client.set_password(passwd_);
acl::redis redis(&client);
std::vector<const acl::redis_node*> nodes;
redis_util::get_all_nodes(redis, nodes);
2019-06-17 10:51:28 +08:00
if (nodes.empty()) {
2016-04-14 22:39:11 +08:00
logger_error("no node of the cluster: %s", addr_.c_str());
return;
}
for (std::vector<const acl::redis_node*>::const_iterator cit
2019-06-17 10:51:28 +08:00
= nodes.begin(); cit != nodes.end(); ++cit) {
2016-04-14 22:39:11 +08:00
const char* addr = (*cit)->get_addr();
2019-06-17 10:51:28 +08:00
if (addr == NULL || *addr == 0) {
2016-04-14 22:39:11 +08:00
logger_error("addr NULL");
continue;
}
config(addr, tokens);
}
}
void redis_commands::config(const char* addr,
const std::vector<acl::string>& tokens)
{
2019-06-17 10:51:28 +08:00
if (tokens.size() < 2) {
2016-04-14 22:39:11 +08:00
config_usage();
return;
}
request_one(addr, tokens);
}
void redis_commands::request_one(const char* addr,
const std::vector<acl::string>& tokens)
{
acl::redis_client client(addr, conn_timeout_, rw_timeout_);
client.set_password(passwd_);
acl::redis redis(&client);
const acl::redis_result* result = redis.request(tokens);
2019-06-17 10:51:28 +08:00
if (result == NULL) {
2016-04-14 22:39:11 +08:00
printf("request error: %s\r\n", redis.result_error());
show_request(tokens);
printf("\r\n");
2019-06-17 10:51:28 +08:00
} else if (!show_result(*result, addr)) {
printf("request error\r\n");
show_request(tokens);
printf("\r\n");
2016-04-14 22:39:11 +08:00
}
}